<!DOCTYPE html>
<html lang="zh-CN">
<head>
  <meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=2">
<meta name="theme-color" content="#222">
<meta name="generator" content="Hexo 6.3.0">
  <link rel="apple-touch-icon" sizes="180x180" href="/images/apple-touch-icon-next.png">
  <link rel="icon" type="image/png" sizes="32x32" href="/images/favicon-32x32-next.png">
  <link rel="icon" type="image/png" sizes="16x16" href="/images/favicon-16x16-next.png">
  <link rel="mask-icon" href="/images/logo.svg" color="#222">

<link rel="stylesheet" href="/css/main.css">


<link rel="stylesheet" href="/lib/font-awesome/css/all.min.css">

<script id="hexo-configurations">
    var NexT = window.NexT || {};
    var CONFIG = {"hostname":"chuangges.gitee.io","root":"/","scheme":"Pisces","version":"7.8.0","exturl":false,"sidebar":{"position":"right","display":"post","padding":18,"offset":12,"onmobile":false},"copycode":{"enable":true,"show_result":true,"style":"mac"},"back2top":{"enable":true,"sidebar":false,"scrollpercent":false},"bookmark":{"enable":false,"color":"#222","save":"auto"},"fancybox":false,"mediumzoom":false,"lazyload":false,"pangu":false,"comments":{"style":"tabs","active":null,"storage":true,"lazyload":false,"nav":null},"algolia":{"hits":{"per_page":10},"labels":{"input_placeholder":"Search for Posts","hits_empty":"We didn't find any results for the search: ${query}","hits_stats":"${hits} results found in ${time} ms"}},"localsearch":{"enable":false,"trigger":"auto","top_n_per_article":1,"unescape":false,"preload":false},"motion":{"enable":true,"async":false,"transition":{"post_block":"fadeIn","post_header":"slideDownIn","post_body":"slideDownIn","coll_header":"slideLeftIn","sidebar":"slideUpIn"}},"path":"search.xml"};
  </script>

  <meta name="description" content="Vue 框架、项目构建、Router、Axios、Vuex">
<meta property="og:type" content="article">
<meta property="og:title" content="Vue 项目构建">
<meta property="og:url" content="https://chuangges.gitee.io/2019/06/05/5-1-vue%E9%A1%B9%E7%9B%AE%E6%9E%84%E5%BB%BA/index.html">
<meta property="og:site_name" content="闯哥要去流浪了">
<meta property="og:description" content="Vue 框架、项目构建、Router、Axios、Vuex">
<meta property="og:locale" content="zh_CN">
<meta property="og:image" content="https://chuangges.gitee.io/images/frame/vuex_base.png">
<meta property="og:image" content="https://chuangges.gitee.io/images/frame/vue_life.png">
<meta property="article:published_time" content="2019-06-04T16:32:55.000Z">
<meta property="article:modified_time" content="2023-10-07T10:54:25.659Z">
<meta property="article:author" content="chuangges">
<meta property="article:tag" content="JS 框架">
<meta name="twitter:card" content="summary">
<meta name="twitter:image" content="https://chuangges.gitee.io/images/frame/vuex_base.png">

<link rel="canonical" href="https://chuangges.gitee.io/2019/06/05/5-1-vue%E9%A1%B9%E7%9B%AE%E6%9E%84%E5%BB%BA/">


<script id="page-configurations">
  // https://hexo.io/docs/variables.html
  CONFIG.page = {
    sidebar: "",
    isHome : false,
    isPost : true,
    lang   : 'zh-CN'
  };
</script>

  <title>Vue 项目构建 | 闯哥要去流浪了</title>
  






  <noscript>
  <style>
  .use-motion .brand,
  .use-motion .menu-item,
  .sidebar-inner,
  .use-motion .post-block,
  .use-motion .pagination,
  .use-motion .comments,
  .use-motion .post-header,
  .use-motion .post-body,
  .use-motion .collection-header { opacity: initial; }

  .use-motion .site-title,
  .use-motion .site-subtitle {
    opacity: initial;
    top: initial;
  }

  .use-motion .logo-line-before i { left: initial; }
  .use-motion .logo-line-after i { right: initial; }
  </style>
</noscript>

<link rel="alternate" href="/atom.xml" title="闯哥要去流浪了" type="application/atom+xml">
</head>

<body itemscope itemtype="http://schema.org/WebPage">
  <div class="container use-motion">
    <div class="headband"></div>

    <header class="header" itemscope itemtype="http://schema.org/WPHeader">
      <div class="header-inner"><div class="site-brand-container">
  <div class="site-nav-toggle">
    <div class="toggle" aria-label="切换导航栏">
      <span class="toggle-line toggle-line-first"></span>
      <span class="toggle-line toggle-line-middle"></span>
      <span class="toggle-line toggle-line-last"></span>
    </div>
  </div>

  <div class="site-meta">

    <a href="/" class="brand" rel="start">
      <span class="logo-line-before"><i></i></span>
      <h1 class="site-title">闯哥要去流浪了</h1>
      <span class="logo-line-after"><i></i></span>
    </a>
      <p class="site-subtitle" itemprop="description">愿你岁月可回首，且以深情共白头</p>
  </div>

  <div class="site-nav-right">
    <div class="toggle popup-trigger">
    </div>
  </div>
</div>




<nav class="site-nav">
  <ul id="menu" class="main-menu menu">
        <li class="menu-item menu-item-home">

    <a href="/" rel="section"><i class="fa fa-home fa-fw"></i>首页</a>

  </li>
        <li class="menu-item menu-item-tags">

    <a href="/tags/" rel="section"><i class="fa fa-tags fa-fw"></i>标签</a>

  </li>
        <li class="menu-item menu-item-categories">

    <a href="/categories/" rel="section"><i class="fa fa-th fa-fw"></i>分类</a>

  </li>
        <li class="menu-item menu-item-archives">

    <a href="/archives/" rel="section"><i class="fa fa-archive fa-fw"></i>归档</a>

  </li>
  </ul>
</nav>




</div>
    </header>

    
  <div class="back-to-top">
    <i class="fa fa-arrow-up"></i>
    <span>0%</span>
  </div>
  <div class="reading-progress-bar"></div>


    <main class="main">
      <div class="main-inner">
        <div class="content-wrap">
          

          <div class="content post posts-expand">
            

    
  
  
  <article itemscope itemtype="http://schema.org/Article" class="post-block" lang="zh-CN">
    <link itemprop="mainEntityOfPage" href="https://chuangges.gitee.io/2019/06/05/5-1-vue%E9%A1%B9%E7%9B%AE%E6%9E%84%E5%BB%BA/">

    <span hidden itemprop="author" itemscope itemtype="http://schema.org/Person">
      <meta itemprop="image" content="/images/chuang.png">
      <meta itemprop="name" content="chuangges">
      <meta itemprop="description" content="chuangge's blog.">
    </span>

    <span hidden itemprop="publisher" itemscope itemtype="http://schema.org/Organization">
      <meta itemprop="name" content="闯哥要去流浪了">
    </span>
      <header class="post-header">
        <h1 class="post-title" itemprop="name headline">
          Vue 项目构建
        </h1>

        <div class="post-meta">
            <span class="post-meta-item">
              <span class="post-meta-item-icon">
                <i class="far fa-calendar"></i>
              </span>
              <span class="post-meta-item-text">发表于</span>

              <time title="创建时间：2019-06-05 00:32:55" itemprop="dateCreated datePublished" datetime="2019-06-05T00:32:55+08:00">2019-06-05</time>
            </span>
              <span class="post-meta-item">
                <span class="post-meta-item-icon">
                  <i class="far fa-calendar-check"></i>
                </span>
                <span class="post-meta-item-text">更新于</span>
                <time title="修改时间：2023-10-07 18:54:25" itemprop="dateModified" datetime="2023-10-07T18:54:25+08:00">2023-10-07</time>
              </span>
            <span class="post-meta-item">
              <span class="post-meta-item-icon">
                <i class="far fa-folder"></i>
              </span>
              <span class="post-meta-item-text">分类于</span>
                <span itemprop="about" itemscope itemtype="http://schema.org/Thing">
                  <a href="/categories/JS-%E6%A1%86%E6%9E%B6/" itemprop="url" rel="index"><span itemprop="name">JS 框架</span></a>
                </span>
            </span>

          <br>
            <span class="post-meta-item" title="本文字数">
              <span class="post-meta-item-icon">
                <i class="far fa-file-word"></i>
              </span>
                <span class="post-meta-item-text">本文字数：</span>
              <span>30k</span>
            </span>
            <span class="post-meta-item" title="阅读时长">
              <span class="post-meta-item-icon">
                <i class="far fa-clock"></i>
              </span>
                <span class="post-meta-item-text">阅读时长 &asymp;</span>
              <span>27 分钟</span>
            </span>
            <div class="post-description">Vue 框架、项目构建、Router、Axios、Vuex</div>

        </div>
      </header>

    
    
    
    <div class="post-body" itemprop="articleBody">

      
        <h1 id="一、Vue-框架"><a href="#一、Vue-框架" class="headerlink" title="一、Vue 框架"></a>一、Vue 框架</h1><ul>
<li><strong>核心思想</strong>：数据驱动的组件系统、轻量高效的前端组件化方案。</li>
<li><strong>开发理念</strong>：渐进式开发 (先构建基础界面后根据需求添加功能)、聚焦视图层的框架、数据驱动的组件化开发、响应式 (页面根据分辨率改变大小，适应式则根据分辨率选择不同页面)。</li>
<li><strong>MVVM 模式</strong>：响应式、双向绑定、数据驱动、视图与数据分离、专注开发页面和业务。</li>
<li><strong>PC UI</strong>：<code>Element、iView、vue-element-admin、iview-admin、vue2-manage</code>。</li>
<li><strong>移动 UI</strong>：<code>Vux、Vant、mint-ui、Muse-UI、vonic、vue-material、cube-ui</code>。</li>
</ul>
<h2 id="全家桶"><a href="#全家桶" class="headerlink" title="全家桶"></a>全家桶</h2><blockquote>
<p>vue 项目的核心构成。</p>
</blockquote>
<ul>
<li><strong>vue-cli</strong>：快速搭建大型单页应用的脚手架。可以自动生成 Vue 项目的目录和文件，通过热加载方式快速启动项目，利用本地 node 服务器实现页面的实时刷新效果。</li>
<li><strong>vue-router</strong>：路由控制。用于配置路径和组件的映射关系，通过路径切换来实现页面切换。</li>
<li><strong>vuex</strong>：状态管理。用于组件间数据的通信和管理，是统一存储所有状态和更新方法的容器。</li>
<li><strong>axios</strong>：异步通信。基于 Promise HTTP 请求客户端，可以同时在浏览器和 nodejs 中使用。</li>
</ul>
<h2 id="双向绑定流程"><a href="#双向绑定流程" class="headerlink" title="双向绑定流程"></a>双向绑定流程</h2><ol>
<li><strong>解析模板为 render 函数。</strong><br>* 模板本质是一串包含指令等逻辑的字符串，最终必须转换成 JS 代码，原因是：必须使用 JS 来处理模板中的逻辑、必须使用 JS 将模板渲染到页面上。<br>* render 函数包含所有的模板信息并返回一个虚拟 DOM，模板用到的 data 属性和 vue 指令都分别变成了 JS 变量和 JS 逻辑，核心是设置对象属性和方法时可以简化代码的 with。</li>
<li><strong>响应式开始监听。</strong><br>* Object.defineProperty 监听：将一个普通 Js 对象传给 Vue 实例的 data 选项时，vue 将遍历此对象属性并通过 Object.defineProperty 将属性全部转为 getter&#x2F;setter。<br>* 将 data 的属性代理到 vm：render 函数中 with(this){} this 指的是 vm (vm.title、vm.list)，其中 title、list 变量都是 data 的属性。</li>
<li><strong>首次渲染显示页面，且绑定依赖。</strong><br>* 初次渲染，执行 updateComponent() 函数，执行 vm._render() 函数。<br>* 执行 render 函数，会访问到 vm.title、vm.list。<br>* 访问 vm.title vm.list 就会被响应式的 get 方法监听到。<br>* 执行 updateComponent()函数，会走到 vdom 的 patch 方法。<br>* patch 将 vnode 渲染成 DOM，初次渲染完成。</li>
<li><strong>data 属性变化，触发 rerender 函数。</strong><br>* 修改属性，被响应式的 set 监听到。<br>* set 中执行 updateComponent。<br>* updateComponent 重新执行 vm._render()。<br>* 生成的 vnode、prevVnode，通过 patch 进行对比。<br>* 局部渲染 html。</li>
</ol>
  <figure class="highlight js"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br><span class="line">42</span><br><span class="line">43</span><br><span class="line">44</span><br><span class="line">45</span><br><span class="line">46</span><br><span class="line">47</span><br><span class="line">48</span><br><span class="line">49</span><br><span class="line">50</span><br><span class="line">51</span><br><span class="line">52</span><br><span class="line">53</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">// 1、解析模板为 render 函数：核心 with 的参数 this 表示 vm。</span></span><br><span class="line">&lt;div id=<span class="string">&quot;app&quot;</span>&gt;</span><br><span class="line">    <span class="language-xml"><span class="tag">&lt;<span class="name">p</span>&gt;</span>&#123;&#123;price&#125;&#125;<span class="tag">&lt;/<span class="name">p</span>&gt;</span></span></span><br><span class="line">&lt;/div&gt;</span><br><span class="line"><span class="title function_">with</span>(<span class="params"><span class="variable language_">this</span></span>)&#123;</span><br><span class="line">    <span class="comment">// _c、_v、_l 函数分别用来创建一个 html 元素、文本节点、数组。</span></span><br><span class="line">    <span class="keyword">return</span> <span class="title function_">_c</span>(</span><br><span class="line">        <span class="string">&#x27;div&#x27;</span>, </span><br><span class="line">        &#123; <span class="attr">attrs</span>: &#123;<span class="string">&quot;id&quot;</span>: <span class="string">&quot;app&quot;</span>&#125; &#125;, </span><br><span class="line">        [ <span class="title function_">_c</span>(<span class="string">&#x27;p&#x27;</span>, [<span class="title function_">_v</span>(<span class="title function_">_s</span>(price))]) ]</span><br><span class="line">    )</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line"><span class="comment">/**</span></span><br><span class="line"><span class="comment">  * <span class="doctag">@title</span> 2、响应式监听</span></span><br><span class="line"><span class="comment">  * <span class="doctag">@prame</span> 闭包：保证 key 的独立作用域。</span></span><br><span class="line"><span class="comment">  * <span class="doctag">@prame</span> getter/setter 在属性被访问和修改时通知而让 vue 追踪依赖，对用户不可见。</span></span><br><span class="line"><span class="comment">  * <span class="doctag">@prame</span> 对象传给 Vue 实例的 data 时要遍历它的所有属性并设置 getter/setter。</span></span><br><span class="line"><span class="comment">**/</span></span><br><span class="line"><span class="keyword">var</span> obj = &#123;&#125;;</span><br><span class="line"><span class="keyword">var</span> data = &#123;</span><br><span class="line">    <span class="attr">price</span>: <span class="number">100</span>,</span><br><span class="line">    <span class="attr">name</span>: <span class="string">&#x27;zhangsan&#x27;</span></span><br><span class="line">&#125;;</span><br><span class="line"><span class="keyword">var</span> key, value;</span><br><span class="line"><span class="keyword">for</span> (key <span class="keyword">in</span> data) &#123;</span><br><span class="line">    (<span class="keyword">function</span> (<span class="params">key</span>) &#123;</span><br><span class="line">        <span class="title class_">Object</span>.<span class="title function_">defineProperty</span>(obj, key, &#123;</span><br><span class="line">            <span class="attr">get</span>: <span class="keyword">function</span>(<span class="params"></span>) &#123;</span><br><span class="line">                <span class="variable language_">console</span>.<span class="title function_">log</span>(<span class="string">&#x27;get&#x27;</span>, key);</span><br><span class="line">                <span class="keyword">return</span> data[key];</span><br><span class="line">            &#125;,</span><br><span class="line">            <span class="attr">set</span>: <span class="keyword">function</span>(<span class="params">newVal</span>) &#123;</span><br><span class="line">                <span class="variable language_">console</span>.<span class="title function_">log</span>(<span class="string">&#x27;set&#x27;</span>, newVal);</span><br><span class="line">                data[key] = newVal;</span><br><span class="line">            &#125;</span><br><span class="line">        &#125;)</span><br><span class="line">    &#125;)(key)</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line"><span class="comment">// 3、vue 模板被渲染为 html</span></span><br><span class="line">vm.<span class="title function_">_update</span>(<span class="params">vnode</span>) &#123;</span><br><span class="line">    <span class="keyword">const</span> prevVnode = vm.<span class="property">_vnode</span>;</span><br><span class="line">    vm.<span class="property">_vnode</span> = vnode;</span><br><span class="line">    <span class="keyword">if</span> (!prevVnode) &#123;    <span class="comment">// 第一次没有值</span></span><br><span class="line">        vm.<span class="property">$el</span> = vm.<span class="title function_">_patch_</span>(vm.<span class="property">$el</span>, vnode);</span><br><span class="line">    &#125; <span class="keyword">else</span> &#123;</span><br><span class="line">        vm.<span class="property">$el</span> = vm.<span class="title function_">_patch_</span>(prevVnode, vnode);</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br><span class="line"><span class="keyword">function</span> <span class="title function_">updateComponent</span>(<span class="params"></span>) &#123;</span><br><span class="line">    vm.<span class="title function_">_update</span>(vm.<span class="title function_">_render</span>());</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>


<h1 id="二、项目构建"><a href="#二、项目构建" class="headerlink" title="二、项目构建"></a>二、项目构建</h1><h2 id="浏览器渲染-SPA"><a href="#浏览器渲染-SPA" class="headerlink" title="浏览器渲染 SPA"></a>浏览器渲染 SPA</h2><blockquote>
<p>浏览器中直接渲染组件的单页面应用程序。整个项目只有一个完整页面 index.html、一个根组件 App.vue。具体流程为：各个组件通过路由拼接到 App.vue router-view，然后将拼接结果转换为代码片段并添加到 index.html 标签中展示出来。</p>
</blockquote>
  <figure class="highlight js"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br><span class="line">42</span><br><span class="line">43</span><br><span class="line">44</span><br><span class="line">45</span><br><span class="line">46</span><br><span class="line">47</span><br><span class="line">48</span><br><span class="line">49</span><br><span class="line">50</span><br><span class="line">51</span><br><span class="line">52</span><br><span class="line">53</span><br><span class="line">54</span><br><span class="line">55</span><br><span class="line">56</span><br><span class="line">57</span><br><span class="line">58</span><br><span class="line">59</span><br><span class="line">60</span><br><span class="line">61</span><br><span class="line">62</span><br><span class="line">63</span><br><span class="line">64</span><br><span class="line">65</span><br><span class="line">66</span><br><span class="line">67</span><br><span class="line">68</span><br><span class="line">69</span><br><span class="line">70</span><br><span class="line">71</span><br><span class="line">72</span><br><span class="line">73</span><br><span class="line">74</span><br><span class="line">75</span><br><span class="line">76</span><br><span class="line">77</span><br><span class="line">78</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">// 初始化目录</span></span><br><span class="line">cnpm install vue @vue/cli webpack -g</span><br><span class="line">vue -V、vue create test</span><br><span class="line"></span><br><span class="line"><span class="comment">// 自定义配置</span></span><br><span class="line">按钮：A -- 全选、空格键 -- 选择与取消、上下 -- 移动</span><br><span class="line">选项：<span class="title class_">Babel</span>、<span class="title class_">Router</span>、<span class="title class_">Vuex</span>、<span class="variable constant_">CSS</span> <span class="title class_">Pre</span>-processors、<span class="title class_">Linter</span> / <span class="title class_">Formatter</span></span><br><span class="line">校验：<span class="title class_">ESLint</span> + <span class="title class_">Prettier</span>、<span class="title class_">Lint</span> on save</span><br><span class="line">保存：<span class="title class_">In</span> dedicated config files、自定义文件名</span><br><span class="line"></span><br><span class="line"><span class="comment">// 启动打包</span></span><br><span class="line">npm start、npm run build</span><br><span class="line"></span><br><span class="line"><span class="comment">// vue.config.js：根目录新建，webpack 自动识别的自定义配置文件。</span></span><br><span class="line"><span class="keyword">let</span> path = <span class="built_in">require</span>(<span class="string">&#x27;path&#x27;</span>)</span><br><span class="line"><span class="keyword">function</span> <span class="title function_">resolve</span>(<span class="params">dir</span>) &#123;</span><br><span class="line">  <span class="keyword">return</span> path.<span class="title function_">join</span>(**dirname, dir)</span><br><span class="line">&#125;</span><br><span class="line"><span class="variable language_">module</span>.<span class="property">exports</span> = &#123;</span><br><span class="line">  <span class="attr">publicPath</span>: <span class="string">&quot;./&quot;</span>,    <span class="comment">// 根路径</span></span><br><span class="line">  <span class="attr">outputDir</span>: <span class="string">&#x27;dist&#x27;</span>,   <span class="comment">// 输出文件目录</span></span><br><span class="line">  <span class="attr">lintOnSave</span>: <span class="literal">false</span>,   <span class="comment">// 取消eslint验证</span></span><br><span class="line">  <span class="attr">configureWebpack</span>: <span class="function"><span class="params">config</span> =&gt;</span> &#123;</span><br><span class="line">    <span class="title class_">Object</span>.<span class="title function_">assign</span>(config, &#123;</span><br><span class="line">      <span class="comment">// 输出配置打包文件名：模块名称.版本号.时间戳</span></span><br><span class="line">      <span class="attr">output</span>: &#123;    <span class="comment">// </span></span><br><span class="line">        <span class="attr">filename</span>: <span class="string">`[name]-<span class="subst">$&#123;process.env.VUE_APP_Version&#125;</span>-<span class="subst">$&#123;Timestamp&#125;</span>.js`</span>,</span><br><span class="line">        <span class="attr">chunkFilename</span>: <span class="string">`[name]-<span class="subst">$&#123;process.env.VUE_APP_Version&#125;</span>-<span class="subst">$&#123;Timestamp&#125;</span>.js`</span></span><br><span class="line">      &#125;,</span><br><span class="line">      <span class="comment">// 配置目录别名：引用路径时减少复杂度</span></span><br><span class="line">      <span class="attr">resolve</span>: &#123;</span><br><span class="line">        <span class="attr">alias</span>: &#123;</span><br><span class="line">          <span class="string">&#x27;@&#x27;</span>: path.<span class="title function_">resolve</span>(**dirname, <span class="string">&#x27;./src&#x27;</span>),</span><br><span class="line">          <span class="string">&#x27;views&#x27;</span>: path.<span class="title function_">resolve</span>(**dirname, <span class="string">&#x27;./src/views&#x27;</span>),</span><br><span class="line">          <span class="string">&#x27;assets&#x27;</span>: path.<span class="title function_">resolve</span>(**dirname, <span class="string">&#x27;./src/assets&#x27;</span>)</span><br><span class="line">        &#125; </span><br><span class="line">      &#125;</span><br><span class="line">    &#125;)</span><br><span class="line">  &#125;,</span><br><span class="line">  <span class="comment">// 配置目录别名</span></span><br><span class="line">  <span class="attr">chainWebpack</span>: <span class="function"><span class="params">config</span> =&gt;</span> &#123;</span><br><span class="line">    config.<span class="property">resolve</span>.<span class="property">alias</span></span><br><span class="line">      .<span class="title function_">set</span>(<span class="string">&#x27;@&#x27;</span>, <span class="title function_">resolve</span>(<span class="string">&#x27;src&#x27;</span>))</span><br><span class="line">      .<span class="title function_">set</span>(<span class="string">&#x27;assets&#x27;</span>, <span class="title function_">resolve</span>(<span class="string">&#x27;src/assets&#x27;</span>))</span><br><span class="line">      .<span class="title function_">set</span>(<span class="string">&#x27;views&#x27;</span>, <span class="title function_">resolve</span>(<span class="string">&#x27;src/views&#x27;</span>))</span><br><span class="line">  &#125;,</span><br><span class="line">  <span class="attr">devServer</span>: &#123;</span><br><span class="line">    <span class="attr">host</span>: <span class="string">&quot;127.0.0.1&quot;</span>,</span><br><span class="line">    <span class="attr">port</span>: <span class="number">8000</span>,</span><br><span class="line">    <span class="attr">https</span>: <span class="literal">false</span>,</span><br><span class="line">    <span class="attr">open</span>: <span class="literal">true</span>,</span><br><span class="line">    <span class="attr">hotOnly</span>: <span class="literal">true</span>,   <span class="comment">// 热更新</span></span><br><span class="line">    <span class="comment">// 配置跨域请求</span></span><br><span class="line">    <span class="comment">// proxy: &#x27;http://localhost:8000&#x27;   // 只有一个代理</span></span><br><span class="line">    <span class="attr">proxy</span>: &#123;                            <span class="comment">// 配置多个代理</span></span><br><span class="line">      <span class="string">&quot;/rest/*&quot;</span>: &#123;  <span class="comment">// 请求地址</span></span><br><span class="line">        <span class="attr">target</span>: <span class="string">&quot;http://172.16.1.12:7071&quot;</span>,  <span class="comment">// 实际映射到的目标地址</span></span><br><span class="line">        <span class="attr">changeOrigin</span>: <span class="literal">true</span>,  <span class="comment">// 是否跨域</span></span><br><span class="line">        <span class="comment">// ws: true,//websocket支持</span></span><br><span class="line">        <span class="attr">secure</span>: <span class="literal">false</span>,  <span class="comment">// https 接口需要配置</span></span><br><span class="line">      &#125;,</span><br><span class="line">      <span class="string">&#x27;/api/a&#x27;</span>: &#123;</span><br><span class="line">        <span class="attr">target</span>: <span class="string">&#x27;http://hongqiao-zatech-channel.test.za-tech.net&#x27;</span>,</span><br><span class="line">        <span class="attr">changeOrigin</span>: <span class="literal">true</span>,</span><br><span class="line">        <span class="attr">pathRewrite</span>: &#123; <span class="string">&#x27;^/api&#x27;</span>: <span class="string">&#x27;/&#x27;</span> &#125;</span><br><span class="line">      &#125;</span><br><span class="line">    &#125;,</span><br><span class="line">    <span class="comment">// 模拟本地数据</span></span><br><span class="line">    <span class="title function_">before</span>(<span class="params">app</span>) &#123;  </span><br><span class="line">      app.<span class="title function_">get</span>(<span class="string">&#x27;/api/seller&#x27;</span>, <span class="function">(<span class="params">req, res</span>) =&gt;</span> &#123;</span><br><span class="line">          res.<span class="title function_">json</span>(&#123; <span class="attr">errno</span>: <span class="number">0</span>, <span class="attr">data</span>: <span class="title function_">requare</span>(<span class="string">&#x27;./data/seller.json&#x27;</span>) &#125;) </span><br><span class="line">      &#125;),</span><br><span class="line">      app.<span class="title function_">post</span>(<span class="string">&#x27;/api/foods&#x27;</span>, <span class="function">(<span class="params">req, res</span>) =&gt;</span> &#123; </span><br><span class="line">          res.<span class="title function_">json</span>(&#123; <span class="attr">errno</span>: <span class="number">0</span>, <span class="attr">data</span>: foods &#125;)</span><br><span class="line">      &#125;)</span><br><span class="line">    &#125;</span><br><span class="line">  &#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>


<h2 id="服务器端渲染-SSR"><a href="#服务器端渲染-SSR" class="headerlink" title="服务器端渲染 SSR"></a>服务器端渲染 SSR</h2><ul>
<li>两种模式：后端首次渲染的单页面应用模式、后端模板渲染模式，区别在于使用后端路由的程度。前者是后端模板渲染和单页面的组合，首次加载时 vue 服务器将当前页面的数据和组件模板生成 html 字符串返回给浏览器，js 资源加载完成后运行单页面应用。</li>
<li>优点：更好的 SEO 而方便搜索引擎爬虫、更快的首屏渲染而无需等待 Js 加载完成。</li>
<li>缺点：更多的服务器负载 (CPU 和内存资源)、更复杂的开发部署 (兼容 Node 环境)。</li>
<li>实现<ul>
<li>选择单页面框架 react&#x2F;vue。</li>
<li>选择 node 服务端框架 express&#x2F;koa2。</li>
<li>实现核心逻辑：node 根据路由渲染单页面组件。</li>
<li>优化开发和发布环境自动化构建工具 webpack。</li>
</ul>
</li>
</ul>
<h2 id="常用配置"><a href="#常用配置" class="headerlink" title="常用配置"></a>常用配置</h2>  <figure class="highlight js"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br><span class="line">42</span><br><span class="line">43</span><br><span class="line">44</span><br><span class="line">45</span><br><span class="line">46</span><br><span class="line">47</span><br><span class="line">48</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">// 1、资源引用</span></span><br><span class="line"><span class="comment">// 适配移动端的库：postcss.config.js</span></span><br><span class="line">cnpm install postcss-px-to-viewport -D</span><br><span class="line"><span class="variable language_">module</span>.<span class="property">exports</span> = &#123;</span><br><span class="line">  <span class="attr">plugins</span>: &#123;</span><br><span class="line">    <span class="string">&#x27;autoprefixer&#x27;</span>: &#123;&#125;,</span><br><span class="line">    <span class="string">&#x27;postcss-px-to-viewport&#x27;</span>: &#123; </span><br><span class="line">      <span class="attr">viewportWidth</span>: <span class="number">750</span>, <span class="comment">// 视窗的宽度，对应的是我们设计稿的宽度，一般是750 </span></span><br><span class="line">      <span class="attr">viewportHeight</span>: <span class="number">1334</span>, <span class="comment">// 视窗的高度，根据750设备的宽度来指定，一般指定 1334，也可不配置 </span></span><br><span class="line">      <span class="attr">unitPrecision</span>: <span class="number">3</span>, <span class="comment">// 指定`px`转换为视窗单位值的小数位数（很多时候无法整除） </span></span><br><span class="line">      <span class="attr">viewportUnit</span>: <span class="string">&#x27;vw&#x27;</span>, <span class="comment">// 指定需要转换成的视窗单位，建议使用vw </span></span><br><span class="line">      <span class="attr">selectorBlackList</span>: [<span class="string">&#x27;.ignore&#x27;</span>, <span class="string">&#x27;.hairlines&#x27;</span>], </span><br><span class="line">      <span class="comment">// 指定不转换为视窗单位的类，可以自定义，可以无限添加,建议定义一至两个通用的类名</span></span><br><span class="line">      <span class="attr">minPixelValue</span>: <span class="number">1</span>, <span class="comment">// 小于或等于`1px`不转换为视窗单位，你也可以设置为你想要的值 </span></span><br><span class="line">      <span class="attr">mediaQuery</span>: <span class="literal">false</span> <span class="comment">// 允许在媒体查询中转换`px`</span></span><br><span class="line">    &#125;</span><br><span class="line">  &#125;</span><br><span class="line">&#125;</span><br><span class="line"><span class="comment">// Ace 代码编辑器插件</span></span><br><span class="line">cnpm install ace-builds -S</span><br><span class="line"><span class="attr">https</span>:<span class="comment">//blog.csdn.net/YoshinoNanjo/article/details/82978668</span></span><br><span class="line"><span class="comment">// 静态资源</span></span><br><span class="line">@<span class="keyword">import</span> <span class="string">&#x27;./reset.css&#x27;</span>;</span><br><span class="line">绝对路径 &lt;img src=<span class="string">&#x27;/images/logo.png&#x27;</span>&gt;;</span><br><span class="line"><span class="keyword">import</span> user <span class="keyword">from</span> <span class="string">&#x27;@/components/user&#x27;</span>;</span><br><span class="line"><span class="keyword">import</span> &#123; getUserInfo &#125; <span class="keyword">from</span> <span class="string">&#x27;./tool.js&#x27;</span>;</span><br><span class="line"></span><br><span class="line"><span class="comment">// 2、环境接口配置</span></span><br><span class="line"><span class="comment">// package.json：开发 development、生产 production、测试 test</span></span><br><span class="line"><span class="string">&quot;scripts&quot;</span>: &#123;</span><br><span class="line">  <span class="string">&quot;serve&quot;</span>: <span class="string">&quot;vue-cli-service serve --mode dev&quot;</span>,</span><br><span class="line">  <span class="string">&quot;build&quot;</span>: <span class="string">&quot;vue-cli-service build --mode prod&quot;</span>,</span><br><span class="line">  <span class="string">&quot;test&quot;</span>: <span class="string">&quot;vue-cli-service build --mode test&quot;</span>,</span><br><span class="line">  <span class="string">&quot;lint&quot;</span>: <span class="string">&quot;vue-cli-service lint&quot;</span></span><br><span class="line">&#125;</span><br><span class="line"><span class="comment">// .env.dev</span></span><br><span class="line"><span class="variable constant_">NODE_ENV</span> = <span class="string">&quot;dev&quot;</span></span><br><span class="line"><span class="variable constant_">VUE_APP_URL</span> = <span class="string">&quot;/apigateway&quot;</span></span><br><span class="line"><span class="comment">// .env.test</span></span><br><span class="line"><span class="variable constant_">NODE_ENV</span> = <span class="string">&quot;production&quot;</span></span><br><span class="line"><span class="variable constant_">VUE_APP_URL</span> = <span class="string">&quot;http://116.228.196.136:10003/apigateway&quot;</span></span><br><span class="line"><span class="comment">// .env.prod</span></span><br><span class="line"><span class="variable constant_">NODE_ENV</span> = <span class="string">&quot;prod&quot;</span></span><br><span class="line"><span class="variable constant_">VUE_APP_URL</span> = <span class="string">&quot;https://api.yongcheng.com:19090/apigateway&quot;</span></span><br><span class="line"></span><br><span class="line"><span class="comment">// 3、静态服务：可配置命令 &quot;script&quot;:&#123; &quot;server&quot;:&quot;live-server ./dist --port=8080&quot; &#125;</span></span><br><span class="line">npm install -g live-server / http-server</span><br><span class="line">live-server / http-server</span><br></pre></td></tr></table></figure>

<h2 id="性能优化"><a href="#性能优化" class="headerlink" title="性能优化"></a>性能优化</h2><ul>
<li>开发过程<ul>
<li><strong>优先使用 v-if</strong>，减少 v-show。</li>
<li><strong>v-for、v-if 不要一起使用</strong>，可通过计算属性先过滤数据。</li>
<li><strong>v-for key</strong> 避免使用 index 作为标识，可采用唯一值来减少新增数据时的开销。</li>
<li><strong>组件和组件库</strong>：事件监听、计时器等需要及时销毁来释放组件资源，组件库引用时尽量通过按需加载的方式。</li>
<li><strong>路由懒加载</strong>：<code>component: () =&gt; import(&quot;views/Login.vue&quot;)</code>。</li>
<li><strong>长列表懒加载</strong>；v-for 生成的列表数据过多时可能造成页面卡顿，可通过 vue-virtual-scroller 等实现懒加载。</li>
<li><strong>图片加载优化</strong>：小图标使用字体图标或 SVG、小型图片通过 base64、webp 的方式、大图放到云服务器通过 CDN 加载、使用框架懒加载的图片。</li>
<li><strong>首屏加载</strong>：页面内容加载完成前使用 loading、进度条、骨架屏(使用一些空白内容的图形来展示未加载内容) 等方式来提升用户体验。</li>
</ul>
</li>
<li>项目过程<ul>
<li><strong>最小化 JS 文件</strong>：webpack4 打包处理，配置 config.optimization.minimize(true)。</li>
<li><strong>图片资源压缩</strong>：打包图片通过 image-webpack-loader 压缩，或者在线无损压缩。</li>
<li><strong>删除沉淀代码</strong>：可通过 Tree-Shaking 插件清理掉无用的沉淀代码。</li>
<li><strong>依赖库 CDN 加速</strong>：可通过 <a target="_blank" rel="external nofollow noopener noreferrer" href="https://www.bootcdn.cn/">BootCDN</a> 引用公共库，vue 通过 script 引入后配置 <code>configureWebpack: &#123; externals: &#123; echarts: &#39;echarts&#39;&#125; &#125;</code>。</li>
<li><strong>开启 gzip 压缩</strong>：可通过 webpack 或后端进行配置。</li>
</ul>
</li>
</ul>
<h1 id="三、路由控制-Router"><a href="#三、路由控制-Router" class="headerlink" title="三、路由控制 Router"></a>三、路由控制 Router</h1><blockquote>
<p>路由根据不同地址展示不同的页面或数据。前端路由多用于 SPA，通过 hash &#x2F; HTML5 historyApi 实现而不涉及到服务器。</p>
</blockquote>
<h2 id="基础使用"><a href="#基础使用" class="headerlink" title="基础使用"></a>基础使用</h2><blockquote>
<p>将组件映射到路由，然后通过 vue-router 渲染。</p>
</blockquote>
<ol>
<li>定义组件：<code>user.vue</code></li>
<li>定义路由配置：<code>var routes = []</code></li>
<li>生成路由对象：<code>var router = new VueRouter(&#123; routes: routes &#125;)</code></li>
<li>注入到实例对象：<code>var app = new Vue(&#123; el: &#39;#app&#39;, router, &#125;)</code></li>
<li>组件中定义渲染标签：<code>router-link、router-view</code></li>
</ol>
<h2 id="路由配置"><a href="#路由配置" class="headerlink" title="路由配置"></a>路由配置</h2><ul>
<li>命名路由：<code>name: &#39;home&#39;</code></li>
<li>嵌套路由：<code>children: [&#123; &#125;]</code></li>
<li>动态路由：<code>path: &#39;/user/:id&#39;</code></li>
<li>命名视图：<code>components: &#123; &#125;</code></li>
</ul>
  <figure class="highlight js"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br><span class="line">42</span><br><span class="line">43</span><br><span class="line">44</span><br><span class="line">45</span><br><span class="line">46</span><br><span class="line">47</span><br><span class="line">48</span><br><span class="line">49</span><br><span class="line">50</span><br><span class="line">51</span><br><span class="line">52</span><br><span class="line">53</span><br><span class="line">54</span><br><span class="line">55</span><br><span class="line">56</span><br><span class="line">57</span><br><span class="line">58</span><br><span class="line">59</span><br><span class="line">60</span><br><span class="line">61</span><br><span class="line">62</span><br><span class="line">63</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">// router/index.js</span></span><br><span class="line"><span class="keyword">import</span> <span class="title class_">Router</span> <span class="keyword">from</span> <span class="string">&#x27;vue-router&#x27;</span></span><br><span class="line"><span class="title class_">Vue</span>.<span class="title function_">use</span>(<span class="title class_">Router</span>)</span><br><span class="line"></span><br><span class="line"><span class="keyword">import</span> user <span class="keyword">from</span> <span class="string">&#x27;@/components/User&#x27;</span></span><br><span class="line"><span class="keyword">import</span> home <span class="keyword">from</span> <span class="string">&#x27;@/components/Home&#x27;</span></span><br><span class="line"></span><br><span class="line"><span class="comment">// 路由懒加载</span></span><br><span class="line"><span class="keyword">const</span> <span class="title function_">home</span> = (<span class="params"></span>) =&gt; <span class="title function_">import</span>(<span class="string">&quot;views/extension/Home.vue&quot;</span>)</span><br><span class="line"></span><br><span class="line"><span class="keyword">export</span> <span class="keyword">default</span> <span class="keyword">new</span> <span class="title class_">Router</span>(&#123;    </span><br><span class="line">  <span class="attr">mode</span>: <span class="string">&quot;history&quot;</span>,            <span class="comment">// 路径模式 </span></span><br><span class="line">  <span class="attr">base</span>: process.<span class="property">env</span>.<span class="property">BASE_URL</span>  <span class="comment">// 基路径(默认&#x27;/&#x27;)           </span></span><br><span class="line">  <span class="attr">linkActiveClass</span>: <span class="string">&#x27;active&#x27;</span>,  <span class="comment">// 链接激活时的class</span></span><br><span class="line"></span><br><span class="line">  <span class="comment">// history 模式下滚动行为，路由切换时页面滚动到指定位置</span></span><br><span class="line">  scrollBehavior (to, <span class="keyword">from</span>, savedPosition) &#123; </span><br><span class="line">    <span class="keyword">if</span>(savedPosition)&#123;  </span><br><span class="line">        <span class="keyword">return</span> savedPosition  <span class="comment">// 原位置</span></span><br><span class="line">    &#125;<span class="keyword">else</span>&#123;</span><br><span class="line">        <span class="keyword">return</span> &#123;<span class="attr">x</span>: <span class="number">0</span>,<span class="attr">y</span>: <span class="number">0</span>&#125;;   <span class="comment">// 顶部</span></span><br><span class="line">    &#125; </span><br><span class="line">    </span><br><span class="line">    <span class="keyword">if</span>(to.<span class="property">hash</span>)&#123;             <span class="comment">// 锚点定位</span></span><br><span class="line">        <span class="keyword">return</span> &#123;<span class="attr">selector</span>: to.<span class="property">hash</span>&#125; </span><br><span class="line">    &#125;</span><br><span class="line">  &#125;,</span><br><span class="line">  </span><br><span class="line">  <span class="attr">routes</span>: [     <span class="comment">// 路由配置</span></span><br><span class="line">    &#123;</span><br><span class="line">      <span class="attr">title</span>: <span class="string">&#x27;登录页&#x27;</span>,</span><br><span class="line">      <span class="attr">alias</span>: <span class="string">&#x27;/b&#x27;</span>,       <span class="comment">// 路径别名</span></span><br><span class="line">      <span class="attr">path</span>: <span class="string">&#x27;/&#x27;</span>, </span><br><span class="line">      <span class="attr">name</span>: <span class="string">&#x27;Index&#x27;</span>,</span><br><span class="line">      <span class="attr">redirect</span>: <span class="string">&#x27;/home&#x27;</span>, <span class="comment">// 重定向(解决首次进入页面时不显示内容的问题)</span></span><br><span class="line">      <span class="attr">component</span>: home</span><br><span class="line">    &#125;, </span><br><span class="line">    &#123;</span><br><span class="line">      <span class="attr">path</span>:<span class="string">&quot;/home&quot;</span>,     <span class="comment">// 静态路由</span></span><br><span class="line">      <span class="attr">name</span>: <span class="string">&#x27;home&#x27;</span>,</span><br><span class="line">      <span class="attr">component</span>: home,</span><br><span class="line">      <span class="attr">children</span>: [&#123;       <span class="comment">// 嵌套路由(须先进 home) </span></span><br><span class="line">          <span class="attr">path</span>: <span class="string">&quot;/phone&quot;</span>,</span><br><span class="line">          <span class="attr">name</span>: <span class="string">&quot;phone&quot;</span>,</span><br><span class="line">          <span class="attr">component</span>: phone</span><br><span class="line">      &#125;]</span><br><span class="line">    &#125;,                  </span><br><span class="line">    &#123;</span><br><span class="line">      <span class="attr">name</span>: <span class="string">&quot;user&quot;</span>,    </span><br><span class="line">      <span class="attr">path</span>: <span class="string">&#x27;/user/:id&#x27;</span>,  <span class="comment">// 动态路由(指定参数形式)   </span></span><br><span class="line">      <span class="attr">component</span>: user, </span><br><span class="line">      <span class="attr">props</span>: <span class="literal">true</span>         <span class="comment">// 组件中接收 id：&#123; props: [id] &#125;  </span></span><br><span class="line">    &#125;,</span><br><span class="line">    &#123;</span><br><span class="line">      <span class="attr">path</span>: <span class="string">&#x27;/name&#x27;</span>,</span><br><span class="line">      <span class="attr">components</span>: &#123;      <span class="comment">// 命名视图(同时渲染多个组件)</span></span><br><span class="line">        <span class="attr">default</span>: <span class="title class_">Foo</span>,</span><br><span class="line">        <span class="attr">a</span>: <span class="title class_">Bar</span>,</span><br><span class="line">        <span class="attr">b</span>: <span class="title class_">Baz</span></span><br><span class="line">      &#125;</span><br><span class="line">    &#125;</span><br><span class="line">  ]</span><br><span class="line">&#125;) </span><br></pre></td></tr></table></figure>


<h2 id="路由模式"><a href="#路由模式" class="headerlink" title="路由模式"></a>路由模式</h2><h3 id="两种模式"><a href="#两种模式" class="headerlink" title="两种模式"></a>两种模式</h3><blockquote>
<p>应用于浏览器的历史记录站，在当前已有的 back、forward、go 的基础上提供了对历史记录进行修改的功能。只是当它们执行修改时，虽然改变了当前URL，但浏览器不会立即向后端发送请求。</p>
</blockquote>
<ul>
<li><strong>hash</strong>：默认模式，浏览器地址中的 # 及其后面的字符串称为 hash，可以通过 window.location.hash 读取，它用来模拟一个完整 URL 但不会被包括在 HTTP 请求中，改变时不会重新加载页面。</li>
<li><strong>history</strong>：利用了 HTML5 新增方法，pushState()、replaceState() 用来对浏览器历史记录栈进行修改，popState 事件用来监听到状态变化。</li>
</ul>
<p>	</p>
<h3 id="404-错误"><a href="#404-错误" class="headerlink" title="404 错误"></a>404 错误</h3><ul>
<li><strong>hash 模式</strong>：只有 # 前面的内容会被包含在请求中。因此对于后端来说，即使没有做到对路由的全覆盖也不会返回 404 错误。</li>
<li><strong>history 模式</strong>：前端 url 必须和实际向后端发起请求的 url 一致，比如 &#x2F;book&#x2F;id ，如果后端缺少对该路由的处理则返回 404 错误。</li>
</ul>
<h3 id="注意问题"><a href="#注意问题" class="headerlink" title="注意问题"></a>注意问题</h3>  <div style="text-indent: 2em">app 开发时一般需要分享页面到第三方 app，但部分 url 不允许带 #。去除 # 需要使用 history 模式，但是有一个问题：在访问二级页面时，刷新操作则会出现 404 错误，那么就需要和后端一起配置 apache 或是 nginx url 重定向，重定向到你的首页路由上即可。</div>
            

<h2 id="路由跳转"><a href="#路由跳转" class="headerlink" title="路由跳转"></a>路由跳转</h2><h3 id="组件标签"><a href="#组件标签" class="headerlink" title="组件标签"></a>组件标签</h3><ul>
<li><strong>跳转标签</strong><ul>
<li>样式：<code>&lt;router-link tag=&quot;li&quot;、active-class=&quot;active&quot; replace&gt;&lt;/router-link&gt;</code>。</li>
<li>导航：普通路由 <code>to= &quot;/path&quot;</code>、动态路由：<code>to=&quot;/user/12&quot;、:to=&quot;&#123; name: &#39;user&#39;, params/query: &#123; id: 1 &#125; &#125;&quot;</code>。</li>
</ul>
</li>
<li><strong>渲染视图</strong><ul>
<li>标签：<code>&lt;router-view name=&quot;user&quot;&gt;&lt;/router-view&gt;</code>。</li>
<li>包裹：缓存 <code>keep-alive</code>、过渡样式 <code>transition</code>。</li>
</ul>
</li>
</ul>
<h3 id="JS-编程式导航"><a href="#JS-编程式导航" class="headerlink" title="JS 编程式导航"></a>JS 编程式导航</h3>  <figure class="highlight js"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">export</span> <span class="keyword">default</span> &#123;</span><br><span class="line">  <span class="attr">methods</span>: &#123;</span><br><span class="line">    <span class="title function_">to_home</span>(<span class="params"></span>)&#123;   <span class="comment">// 字符串 和 对象</span></span><br><span class="line">      <span class="variable language_">this</span>.<span class="property">$router</span>.<span class="title function_">push</span>(<span class="string">&quot;home&quot;</span>)      </span><br><span class="line">      <span class="variable language_">this</span>.<span class="property">$router</span>.<span class="title function_">push</span>(&#123; <span class="attr">path</span>: <span class="string">&#x27;/login?url=&#x27;</span> + <span class="variable language_">this</span>.<span class="property">$route</span>.<span class="property">path</span> &#125;)  </span><br><span class="line">    &#125;,</span><br><span class="line">    <span class="title function_">to_user</span>(<span class="params"></span>)&#123;  <span class="comment">// 命名路由 和 查询参数</span></span><br><span class="line">      <span class="variable language_">this</span>.<span class="property">$router</span>.<span class="title function_">push</span>(&#123; <span class="attr">name</span>: <span class="string">&#x27;user&#x27;</span>, <span class="attr">params</span>: &#123; <span class="attr">id</span>: <span class="number">123</span> &#125;&#125;)  </span><br><span class="line">      <span class="variable language_">this</span>.<span class="property">$router</span>.<span class="title function_">push</span>(&#123; <span class="attr">path</span>: <span class="string">&#x27;user&#x27;</span>, <span class="attr">query</span>: &#123; <span class="attr">id</span>: <span class="number">123</span> &#125;&#125;)   </span><br><span class="line">    &#125;,</span><br><span class="line">    <span class="title function_">to_other</span>(<span class="params"></span>)&#123;</span><br><span class="line">      <span class="variable language_">this</span>.<span class="property">$router</span>.<span class="title function_">go</span>(n)         <span class="comment">// 前进</span></span><br><span class="line">      <span class="variable language_">this</span>.<span class="property">$router</span>.<span class="title function_">back</span>()        <span class="comment">// 后退</span></span><br><span class="line">      <span class="variable language_">this</span>.<span class="property">$router</span>.<span class="title function_">forward</span>()</span><br><span class="line">      <span class="variable language_">this</span>.<span class="property">$router</span>.<span class="title function_">replace</span>()     <span class="comment">// 替换掉当前的history记录</span></span><br><span class="line">    &#125;,</span><br><span class="line">    <span class="title function_">get_obj</span>(<span class="params"></span>)&#123;</span><br><span class="line">      <span class="variable language_">console</span>.<span class="title function_">log</span>(<span class="variable language_">this</span>.<span class="property">$route</span>)   <span class="comment">// 路由对象(包括 path、params 等)</span></span><br><span class="line">    &#125;</span><br><span class="line">  &#125;   </span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>


<h2 id="动态路由传参"><a href="#动态路由传参" class="headerlink" title="动态路由传参"></a>动态路由传参</h2><ul>
<li>方式<ul>
<li><strong>path</strong>：<code>to=&quot;/user/12&quot;</code></li>
<li><strong>params</strong>：<code>:to=&quot;&#123; name: &#39;user&#39;, params: &#123; id: 1 &#125; &#125;&quot;</code></li>
<li><strong>query</strong>：<code>:to=&quot;&#123; name: &#39;user&#39;, query: &#123; id: 1 &#125; &#125;&quot;</code></li>
</ul>
</li>
<li>注意<ul>
<li>通过 path&#x2F;params 传参时，需要在路由配置中指定参数形式 <code>path: &#39;/user/:id&#39;</code>。</li>
<li>通过 params&#x2F;query 传参时，参数必须是对象格式并绑定 to 属性 <code>v-bind:</code>。</li>
<li>跳转后的组件中获取参数 <code>this.$route.params/query.id</code>。</li>
</ul>
</li>
</ul>
<h2 id="导航钩子"><a href="#导航钩子" class="headerlink" title="导航钩子"></a>导航钩子</h2><blockquote>
<p>用于路由跳转时执行任务或不满足条件时取消跳转。</p>
</blockquote>
<h3 id="分类"><a href="#分类" class="headerlink" title="分类"></a>分类</h3><ul>
<li><strong>全局钩子</strong>：beforeEach，常用于登录权限等验证。</li>
<li><strong>路由钩子</strong>：beforeLeave &#x2F; beforeEnter。</li>
<li><strong>组件钩子</strong>：beforeRouteLeave 用于清除计时器、提示保存内容、存储信息等，beforeRouteEnter 用于在跳转完成前获取数据。</li>
</ul>
<h3 id="参数"><a href="#参数" class="headerlink" title="参数"></a>参数</h3><ul>
<li><strong>to</strong>：目标路由对象。</li>
<li><strong>from</strong>：当前路由对象。</li>
<li><strong>next</strong>：必须调用的函数，否则就是死循环。<ul>
<li><code>next()</code>：执行下一个钩子，如果钩子全部执行完成则导航状态为 confirmed。</li>
<li><code>next(false)</code>：中断当前导航，即重置到 from 路由对应的地址。</li>
<li><code>next(&#39;/&#39;)、next(&#123;path: &#39;/&#39;&#125;)</code>：中断掉当前导航并跳转到新地址。</li>
<li><code>next(error)</code>：如果传入一个 Error 实例，则导航被终止并会将错误传递给 router.onError() 注册的回调。</li>
</ul>
</li>
</ul>
<h1 id="四、异步通信-Axios"><a href="#四、异步通信-Axios" class="headerlink" title="四、异步通信 Axios"></a>四、异步通信 Axios</h1><h2 id="基础使用-1"><a href="#基础使用-1" class="headerlink" title="基础使用"></a>基础使用</h2>  <figure class="highlight js"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br></pre></td><td class="code"><pre><span class="line"><span class="variable language_">this</span>.<span class="property">$axios</span>.<span class="title function_">get</span>(<span class="string">&#x27;/user?id=12&#x27;</span>)</span><br><span class="line">  .<span class="title function_">then</span>( <span class="function"><span class="params">res</span> =&gt;</span> &#123; &#125;)</span><br><span class="line">  .<span class="title function_">catch</span>( <span class="function"><span class="params">err</span> =&gt;</span> &#123; &#125;)</span><br><span class="line"></span><br><span class="line"><span class="keyword">let</span> prames = <span class="title class_">Object</span>.<span class="title function_">assign</span>(&#123;&#125;, <span class="variable language_">this</span>.<span class="property">form_data</span>)</span><br><span class="line"><span class="variable language_">this</span>.$axios(&#123; </span><br><span class="line">  <span class="attr">url</span>: url,</span><br><span class="line">  <span class="attr">method</span>: <span class="string">&#x27;post&#x27;</span>,</span><br><span class="line">  <span class="attr">data</span>: <span class="variable language_">this</span>.<span class="property">$qs</span>.<span class="title function_">stringify</span>(prames)</span><br><span class="line">&#125;).<span class="title function_">then</span>(<span class="function">(<span class="params">res</span>)=&gt;</span>&#123;</span><br><span class="line">  <span class="variable language_">console</span>.<span class="title function_">log</span>(res)</span><br><span class="line">&#125;)</span><br><span class="line"></span><br><span class="line"><span class="comment">// formData 形式上传数据</span></span><br><span class="line">　<span class="keyword">let</span> formData = <span class="keyword">new</span> <span class="title class_">FormData</span>();</span><br><span class="line">formData.<span class="title function_">append</span>(<span class="string">&#x27;file&#x27;</span>, file);    </span><br><span class="line">　axios.<span class="title function_">post</span>(<span class="string">&#x27;url&#x27;</span>, formData, &#123;</span><br><span class="line">　　<span class="attr">headers</span>: &#123; <span class="string">&#x27;Content-Type&#x27;</span>: <span class="string">&#x27;multipart/form-data&#x27;</span> &#125;</span><br><span class="line">　&#125;)</span><br></pre></td></tr></table></figure>


<h2 id="请求-API"><a href="#请求-API" class="headerlink" title="请求 API"></a>请求 API</h2><ul>
<li>请求：<code>axios(config)、axios(url, [config])</code></li>
<li>并发：<code>axios.all(arr)、axios.spread(callback)</code></li>
<li>别名：<code>axios.get(url, [config])、axios.post(url, [data], [config])</code></li>
</ul>
<h2 id="自定义配置"><a href="#自定义配置" class="headerlink" title="自定义配置"></a>自定义配置</h2><h3 id="封装-axios"><a href="#封装-axios" class="headerlink" title="封装 axios"></a>封装 axios</h3>  <figure class="highlight js"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br><span class="line">42</span><br><span class="line">43</span><br><span class="line">44</span><br><span class="line">45</span><br><span class="line">46</span><br><span class="line">47</span><br><span class="line">48</span><br><span class="line">49</span><br><span class="line">50</span><br><span class="line">51</span><br><span class="line">52</span><br><span class="line">53</span><br><span class="line">54</span><br><span class="line">55</span><br><span class="line">56</span><br><span class="line">57</span><br><span class="line">58</span><br><span class="line">59</span><br><span class="line">60</span><br><span class="line">61</span><br><span class="line">62</span><br><span class="line">63</span><br><span class="line">64</span><br><span class="line">65</span><br><span class="line">66</span><br><span class="line">67</span><br><span class="line">68</span><br><span class="line">69</span><br><span class="line">70</span><br><span class="line">71</span><br><span class="line">72</span><br><span class="line">73</span><br><span class="line">74</span><br><span class="line">75</span><br><span class="line">76</span><br><span class="line">77</span><br><span class="line">78</span><br><span class="line">79</span><br><span class="line">80</span><br><span class="line">81</span><br><span class="line">82</span><br><span class="line">83</span><br><span class="line">84</span><br><span class="line">85</span><br><span class="line">86</span><br><span class="line">87</span><br><span class="line">88</span><br><span class="line">89</span><br><span class="line">90</span><br><span class="line">91</span><br><span class="line">92</span><br><span class="line">93</span><br><span class="line">94</span><br><span class="line">95</span><br><span class="line">96</span><br><span class="line">97</span><br><span class="line">98</span><br><span class="line">99</span><br><span class="line">100</span><br><span class="line">101</span><br><span class="line">102</span><br><span class="line">103</span><br><span class="line">104</span><br><span class="line">105</span><br><span class="line">106</span><br><span class="line">107</span><br><span class="line">108</span><br><span class="line">109</span><br><span class="line">110</span><br><span class="line">111</span><br><span class="line">112</span><br><span class="line">113</span><br><span class="line">114</span><br><span class="line">115</span><br><span class="line">116</span><br><span class="line">117</span><br><span class="line">118</span><br><span class="line">119</span><br><span class="line">120</span><br><span class="line">121</span><br><span class="line">122</span><br><span class="line">123</span><br><span class="line">124</span><br><span class="line">125</span><br><span class="line">126</span><br><span class="line">127</span><br><span class="line">128</span><br><span class="line">129</span><br><span class="line">130</span><br><span class="line">131</span><br><span class="line">132</span><br><span class="line">133</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">// axios.js</span></span><br><span class="line"><span class="keyword">import</span> axios <span class="keyword">from</span> <span class="string">&#x27;axios&#x27;</span></span><br><span class="line"><span class="keyword">import</span> router <span class="keyword">from</span> <span class="string">&#x27;@/router&#x27;</span></span><br><span class="line"><span class="keyword">import</span> store <span class="keyword">from</span> <span class="string">&#x27;./store&#x27;</span></span><br><span class="line"><span class="keyword">import</span> &#123; crypto, random, randomWord &#125; <span class="keyword">from</span> <span class="string">&#x27;./assets/js/tool.js&#x27;</span>;</span><br><span class="line"></span><br><span class="line"><span class="comment">// 创建axios实例</span></span><br><span class="line"><span class="keyword">const</span> service = axios.<span class="title function_">create</span>(&#123;</span><br><span class="line">  <span class="attr">baseURL</span>: process.<span class="property">env</span>.<span class="property">VUE_APP_URL</span>,</span><br><span class="line">  <span class="comment">// timeout: 10000,            // 请求超时时间</span></span><br><span class="line">  <span class="attr">responseType</span>: <span class="string">&quot;json&quot;</span>,</span><br><span class="line">&#125;)</span><br><span class="line"></span><br><span class="line"><span class="comment">// 请求拦截器</span></span><br><span class="line">service.<span class="property">interceptors</span>.<span class="property">request</span>.<span class="title function_">use</span>(</span><br><span class="line">  <span class="function"><span class="params">config</span> =&gt;</span> &#123;</span><br><span class="line">    <span class="comment">// 1：加密数据</span></span><br><span class="line">    <span class="keyword">if</span>(config.<span class="property">headers</span>.<span class="property">level</span> == <span class="number">1</span>)&#123;  </span><br><span class="line">        <span class="keyword">const</span> <span class="variable constant_">KP</span> = &#123;</span><br><span class="line">          <span class="attr">key</span>: <span class="title function_">randomWord</span>(<span class="literal">true</span>, <span class="number">16</span>, <span class="number">16</span>),  <span class="comment">// 秘钥</span></span><br><span class="line">          <span class="attr">iv</span>: <span class="title function_">randomWord</span>(<span class="literal">true</span>, <span class="number">16</span>, <span class="number">16</span>)    <span class="comment">// 偏移量</span></span><br><span class="line">        &#125;;</span><br><span class="line">        config.<span class="property">data</span> = crypto.<span class="title class_">AESEnc</span>(<span class="title class_">JSON</span>.<span class="title function_">stringify</span>(config.<span class="property">data</span>), <span class="variable constant_">KP</span>.<span class="property">key</span>)</span><br><span class="line"></span><br><span class="line">        <span class="title class_">Object</span>.<span class="title function_">assign</span>(config.<span class="property">headers</span>, &#123;</span><br><span class="line">          <span class="string">&quot;Content-Type&quot;</span>: <span class="string">&quot;application/json;charset=utf-8&quot;</span>,</span><br><span class="line">          <span class="attr">dataFormat</span>: <span class="string">&quot;json&quot;</span>,</span><br><span class="line">          <span class="attr">authMethod</span>: <span class="string">&quot;no&quot;</span>,</span><br><span class="line">          <span class="attr">signAlgo</span>: <span class="string">&quot;NO&quot;</span>,</span><br><span class="line">          <span class="attr">transAlgo</span>: <span class="string">&quot;AES&quot;</span>,</span><br><span class="line">          <span class="attr">shareKey</span>: <span class="variable constant_">KP</span>.<span class="property">key</span>,</span><br><span class="line">          <span class="attr">timestamp</span>: <span class="keyword">new</span> <span class="title class_">Date</span>().<span class="title function_">getTime</span>(),</span><br><span class="line">          <span class="attr">nonce</span>: <span class="title class_">String</span>(<span class="title function_">random</span>(<span class="number">0</span>, <span class="number">100</span>))</span><br><span class="line">        &#125;)</span><br><span class="line">    &#125;</span><br><span class="line">        </span><br><span class="line">    <span class="comment">// 让每个请求携带 token</span></span><br><span class="line">    <span class="keyword">if</span> (store.<span class="property">getters</span>.<span class="property">token</span>) &#123;</span><br><span class="line">        config.<span class="property">data</span> = <span class="title class_">Object</span>.<span class="title function_">assign</span>(&#123; <span class="attr">token</span>: store.<span class="property">getters</span>.<span class="property">token</span> &#125;, config.<span class="property">data</span>)</span><br><span class="line">    &#125;</span><br><span class="line"></span><br><span class="line">    <span class="comment">// 设置表头  &#x27;application/json&#x27;</span></span><br><span class="line">    config.<span class="property">headers</span>[<span class="string">&#x27;Content-Type&#x27;</span>] = <span class="string">&#x27;application/json;charset=utf-8&#x27;</span></span><br><span class="line"></span><br><span class="line">    <span class="comment">// 异步请求的取消操作</span></span><br><span class="line">    <span class="keyword">let</span> <span class="title class_">CancelToken</span> = axios.<span class="property">CancelToken</span>;  </span><br><span class="line">    <span class="keyword">let</span> cancel</span><br><span class="line">    config.<span class="property">cancelToken</span> = <span class="keyword">new</span> <span class="title class_">CancelToken</span>( <span class="function"><span class="params">c</span> =&gt;</span> &#123;</span><br><span class="line">        cancel = c;</span><br><span class="line">    &#125;)</span><br><span class="line">    <span class="title function_">cancel</span>()</span><br><span class="line"></span><br><span class="line">    <span class="comment">// 状态更新</span></span><br><span class="line">    store.<span class="title function_">commit</span>(<span class="string">&#x27;showLoad&#x27;</span>, &#123; <span class="attr">status</span>: <span class="number">1</span>, <span class="attr">msg</span>: <span class="string">&quot;&quot;</span> &#125;)</span><br><span class="line">    <span class="keyword">return</span> config</span><br><span class="line">  &#125;,</span><br><span class="line">  <span class="function"><span class="params">error</span> =&gt;</span> &#123;</span><br><span class="line">    store.<span class="title function_">commit</span>(<span class="string">&#x27;showLoad&#x27;</span>, &#123; <span class="attr">status</span>: <span class="number">2</span>, <span class="attr">msg</span>: <span class="string">&quot;&quot;</span> &#125;)</span><br><span class="line">    <span class="keyword">return</span> <span class="title class_">Promise</span>.<span class="title function_">reject</span>(error)</span><br><span class="line">  &#125;</span><br><span class="line">)</span><br><span class="line"><span class="comment">// 响应拦截器</span></span><br><span class="line">service.<span class="property">interceptors</span>.<span class="property">response</span>.<span class="title function_">use</span>(</span><br><span class="line">  <span class="function"><span class="params">response</span> =&gt;</span> &#123;</span><br><span class="line">    <span class="comment">// 解密返回数据</span></span><br><span class="line">    response.<span class="property">data</span> = <span class="title class_">JSON</span>.<span class="title function_">parse</span>(crypto.<span class="title class_">AESDec</span>(response.<span class="property">data</span>, response.<span class="property">config</span>.<span class="property">headers</span>.<span class="property">shareKey</span>))</span><br><span class="line"></span><br><span class="line">    <span class="keyword">if</span>(response.<span class="property">data</span>.<span class="property">CResultCde</span> == <span class="string">&quot;0000&quot;</span>)&#123;</span><br><span class="line">        store.<span class="title function_">commit</span>(<span class="string">&#x27;hideLoad&#x27;</span>)</span><br><span class="line">    &#125;<span class="keyword">else</span>&#123;</span><br><span class="line">        store.<span class="title function_">commit</span>(<span class="string">&#x27;showLoad&#x27;</span>, &#123; <span class="attr">status</span>: <span class="number">2</span>, <span class="attr">msg</span>: response.<span class="property">data</span>.<span class="property">CResultMsg</span> &#125;)</span><br><span class="line">    &#125;</span><br><span class="line">    <span class="keyword">return</span> <span class="title class_">Promise</span>.<span class="title function_">resolve</span>(response)</span><br><span class="line">  &#125;,</span><br><span class="line">  <span class="function"><span class="params">error</span> =&gt;</span> &#123;</span><br><span class="line">    store.<span class="title function_">commit</span>(<span class="string">&#x27;showLoad&#x27;</span>, &#123; <span class="attr">status</span>: <span class="number">2</span>, <span class="attr">msg</span>: <span class="string">&quot;&quot;</span> &#125;)</span><br><span class="line">    <span class="keyword">return</span> <span class="title class_">Promise</span>.<span class="title function_">reject</span>(error)</span><br><span class="line">  &#125;</span><br><span class="line">)</span><br><span class="line"><span class="comment">// 导出对象</span></span><br><span class="line"><span class="keyword">export</span> <span class="keyword">default</span> service</span><br><span class="line"></span><br><span class="line"><span class="comment">// 导出方法</span></span><br><span class="line"><span class="keyword">export</span> <span class="keyword">function</span> <span class="title function_">indexQRCode</span>(<span class="params">data</span>)&#123;  <span class="comment">// 不加密</span></span><br><span class="line">  <span class="keyword">return</span> <span class="title function_">_request</span>(<span class="string">&#x27;/getHomePageQRcode&#x27;</span>, <span class="string">&#x27;post&#x27;</span>, data, &#123; <span class="attr">level</span>: <span class="number">2</span> &#125;)</span><br><span class="line">&#125;</span><br><span class="line"><span class="keyword">export</span> <span class="keyword">function</span> <span class="title function_">getProduct</span>(<span class="params">data</span>)&#123;   <span class="comment">// 加密</span></span><br><span class="line">  <span class="keyword">const</span> headers = &#123; </span><br><span class="line">    <span class="attr">level</span>: <span class="number">1</span>,     </span><br><span class="line">    <span class="attr">module</span>: <span class="string">&quot;prodAction&quot;</span>, </span><br><span class="line">    <span class="attr">method</span>: <span class="string">&quot;getProductInfoList&quot;</span></span><br><span class="line">  &#125;</span><br><span class="line">  <span class="keyword">return</span> <span class="title function_">_request</span>(<span class="string">&#x27;&#x27;</span>, <span class="string">&#x27;post&#x27;</span>, data, headers)</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line"><span class="comment">// 资料上传</span></span><br><span class="line"><span class="keyword">export</span> <span class="keyword">function</span> <span class="title function_">batchFileUpload</span>(<span class="params">data, progressfn</span>)&#123;</span><br><span class="line">  <span class="keyword">return</span> <span class="title function_">form_upload</span>(<span class="string">&#x27;/UploadController&#x27;</span>, data, progressfn)</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line"><span class="comment">// 文件数据上传</span></span><br><span class="line"><span class="keyword">function</span> <span class="title function_">form_upload</span>(<span class="params">url, data, progressfn</span>)&#123;</span><br><span class="line">  <span class="comment">// formData 需要纯净的 axios 请求</span></span><br><span class="line">  <span class="keyword">const</span> formAxios = axios.<span class="title function_">create</span>(&#123;</span><br><span class="line">    <span class="attr">baseURL</span>: process.<span class="property">env</span>.<span class="property">VUE_APP_URL</span>,</span><br><span class="line">    <span class="attr">responseType</span>: <span class="string">&quot;json&quot;</span>,</span><br><span class="line">    <span class="comment">// timeout: 10000,</span></span><br><span class="line">  &#125;)</span><br><span class="line"></span><br><span class="line">  <span class="keyword">return</span> <span class="title function_">formAxios</span>(&#123;</span><br><span class="line">    <span class="attr">method</span>: <span class="string">&#x27;post&#x27;</span>,</span><br><span class="line">    <span class="attr">data</span>: data,</span><br><span class="line">    <span class="attr">headers</span>: &#123;</span><br><span class="line">      <span class="string">&#x27;Content-Type&#x27;</span>: <span class="string">&quot;multipart/form-data&quot;</span></span><br><span class="line">    &#125;,</span><br><span class="line">    <span class="title function_">onUploadProgress</span>(<span class="params">progressEvent</span>) &#123; <span class="comment">// 原生获取上传进度的事件</span></span><br><span class="line">      <span class="comment">// lengthComputable 主要表明总工作量和已完成工作是否可以被测量</span></span><br><span class="line">      progressEvent.<span class="property">lengthComputable</span> &amp;&amp; <span class="title function_">progressfn</span>(progressEvent);</span><br><span class="line">    &#125;</span><br><span class="line">  &#125;)</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line"><span class="comment">// 表单数据上传</span></span><br><span class="line"><span class="keyword">function</span> <span class="title function_">_request</span> (url, methods, data, headers = &#123; <span class="attr">level</span>: <span class="number">1</span> &#125;, params = &#123;&#125;) &#123;</span><br><span class="line">  <span class="keyword">return</span> <span class="title function_">service</span>(&#123;</span><br><span class="line">    <span class="attr">method</span>: methods,</span><br><span class="line">    <span class="attr">url</span>: headers.<span class="property">level</span> == <span class="number">1</span> ? <span class="string">&quot;/api&quot;</span> : url,</span><br><span class="line">    <span class="attr">data</span>: data,</span><br><span class="line">    <span class="attr">params</span>: <span class="title class_">Object</span>.<span class="title function_">assign</span>(params),</span><br><span class="line">    <span class="attr">headers</span>: <span class="title class_">Object</span>.<span class="title function_">assign</span>(headers),</span><br><span class="line">    <span class="attr">responseType</span>: headers.<span class="property">level</span> == <span class="number">1</span> ? <span class="string">&quot;text&quot;</span> : <span class="string">&quot;json&quot;</span></span><br><span class="line">  &#125;)</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>


<h3 id="引用方法"><a href="#引用方法" class="headerlink" title="引用方法"></a>引用方法</h3>  <figure class="highlight js"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">// main.js 全局引用</span></span><br><span class="line"><span class="keyword">import</span> http <span class="keyword">from</span> <span class="string">&#x27;./axios&#x27;</span></span><br><span class="line"><span class="title class_">Vue</span>.<span class="property"><span class="keyword">prototype</span></span>.<span class="property">$axios</span> = http</span><br><span class="line"></span><br><span class="line"><span class="comment">// 局部引用</span></span><br><span class="line"><span class="keyword">import</span> &#123; indexQRCode &#125; <span class="keyword">from</span> <span class="string">&#x27;@/axios&#x27;</span></span><br></pre></td></tr></table></figure>
<h3 id="加密方法"><a href="#加密方法" class="headerlink" title="加密方法"></a>加密方法</h3>  <figure class="highlight js"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br><span class="line">42</span><br><span class="line">43</span><br><span class="line">44</span><br><span class="line">45</span><br><span class="line">46</span><br><span class="line">47</span><br><span class="line">48</span><br><span class="line">49</span><br><span class="line">50</span><br><span class="line">51</span><br><span class="line">52</span><br><span class="line">53</span><br><span class="line">54</span><br><span class="line">55</span><br><span class="line">56</span><br><span class="line">57</span><br><span class="line">58</span><br><span class="line">59</span><br><span class="line">60</span><br><span class="line">61</span><br><span class="line">62</span><br><span class="line">63</span><br><span class="line">64</span><br><span class="line">65</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">// tool.js</span></span><br><span class="line"></span><br><span class="line"><span class="comment">// 随机整数</span></span><br><span class="line"><span class="keyword">export</span> <span class="keyword">function</span> <span class="title function_">random</span>(<span class="params">min, max</span>)&#123;</span><br><span class="line">  <span class="keyword">if</span>(max == <span class="literal">null</span>)&#123;</span><br><span class="line">    max = min;  </span><br><span class="line">    min = <span class="number">0</span>;</span><br><span class="line">  &#125;</span><br><span class="line">  <span class="keyword">return</span> min + <span class="title class_">Math</span>.<span class="title function_">floor</span>(<span class="title class_">Math</span>.<span class="title function_">random</span>()*(max-min+<span class="number">1</span>))</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line"><span class="comment">/*</span></span><br><span class="line"><span class="comment">** randomWord 产生任意长度随机字母数字组合</span></span><br><span class="line"><span class="comment">** randomFlag-是否任意长度 min-任意长度最小位[固定位数] max-任意长度最大位</span></span><br><span class="line"><span class="comment">*/</span></span><br><span class="line"><span class="keyword">export</span> <span class="keyword">function</span> <span class="title function_">randomWord</span>(<span class="params">randomFlag, min, max</span>)&#123;</span><br><span class="line">  <span class="keyword">var</span> str = <span class="string">&quot;&quot;</span>,</span><br><span class="line">  pos = <span class="string">&quot;&quot;</span>,</span><br><span class="line">  range = min,</span><br><span class="line">  arr = [<span class="string">&#x27;0&#x27;</span>, <span class="string">&#x27;1&#x27;</span>, <span class="string">&#x27;2&#x27;</span>, <span class="string">&#x27;3&#x27;</span>, <span class="string">&#x27;4&#x27;</span>, <span class="string">&#x27;5&#x27;</span>, <span class="string">&#x27;6&#x27;</span>, <span class="string">&#x27;7&#x27;</span>, <span class="string">&#x27;8&#x27;</span>, <span class="string">&#x27;9&#x27;</span>, </span><br><span class="line">        <span class="string">&#x27;a&#x27;</span>, <span class="string">&#x27;b&#x27;</span>, <span class="string">&#x27;c&#x27;</span>, <span class="string">&#x27;d&#x27;</span>, <span class="string">&#x27;e&#x27;</span>, <span class="string">&#x27;f&#x27;</span>, <span class="string">&#x27;g&#x27;</span>, <span class="string">&#x27;h&#x27;</span>, <span class="string">&#x27;i&#x27;</span>, <span class="string">&#x27;j&#x27;</span>, <span class="string">&#x27;k&#x27;</span>, </span><br><span class="line">        <span class="string">&#x27;l&#x27;</span>, <span class="string">&#x27;m&#x27;</span>, <span class="string">&#x27;n&#x27;</span>, <span class="string">&#x27;o&#x27;</span>, <span class="string">&#x27;p&#x27;</span>, <span class="string">&#x27;q&#x27;</span>, <span class="string">&#x27;r&#x27;</span>, <span class="string">&#x27;s&#x27;</span>, <span class="string">&#x27;t&#x27;</span>, <span class="string">&#x27;u&#x27;</span>, <span class="string">&#x27;v&#x27;</span>, </span><br><span class="line">        <span class="string">&#x27;w&#x27;</span>, <span class="string">&#x27;x&#x27;</span>, <span class="string">&#x27;y&#x27;</span>, <span class="string">&#x27;z&#x27;</span>, <span class="string">&#x27;A&#x27;</span>, <span class="string">&#x27;B&#x27;</span>, <span class="string">&#x27;C&#x27;</span>, <span class="string">&#x27;D&#x27;</span>, <span class="string">&#x27;E&#x27;</span>, <span class="string">&#x27;F&#x27;</span>, <span class="string">&#x27;G&#x27;</span>, </span><br><span class="line">        <span class="string">&#x27;H&#x27;</span>, <span class="string">&#x27;I&#x27;</span>, <span class="string">&#x27;J&#x27;</span>, <span class="string">&#x27;K&#x27;</span>, <span class="string">&#x27;L&#x27;</span>, <span class="string">&#x27;M&#x27;</span>, <span class="string">&#x27;N&#x27;</span>, <span class="string">&#x27;O&#x27;</span>, <span class="string">&#x27;P&#x27;</span>, <span class="string">&#x27;Q&#x27;</span>, <span class="string">&#x27;R&#x27;</span>, </span><br><span class="line">        <span class="string">&#x27;S&#x27;</span>, <span class="string">&#x27;T&#x27;</span>, <span class="string">&#x27;U&#x27;</span>, <span class="string">&#x27;V&#x27;</span>, <span class="string">&#x27;W&#x27;</span>, <span class="string">&#x27;X&#x27;</span>, <span class="string">&#x27;Y&#x27;</span>, <span class="string">&#x27;Z&#x27;</span>];</span><br><span class="line">  <span class="comment">// 随机产生</span></span><br><span class="line">  <span class="keyword">if</span>(randomFlag)&#123;</span><br><span class="line">      range = <span class="title class_">Math</span>.<span class="title function_">round</span>(<span class="title class_">Math</span>.<span class="title function_">random</span>() * (max-min)) + min;</span><br><span class="line">  &#125;</span><br><span class="line">  <span class="keyword">for</span>(<span class="keyword">var</span> i=<span class="number">0</span>; i &lt; range; i++)&#123;</span><br><span class="line">      pos = <span class="title class_">Math</span>.<span class="title function_">round</span>(<span class="title class_">Math</span>.<span class="title function_">random</span>() * (arr.<span class="property">length</span>-<span class="number">1</span>));</span><br><span class="line">      str += arr[pos];</span><br><span class="line">  &#125;</span><br><span class="line">  <span class="keyword">return</span> str;</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line"><span class="comment">/*</span></span><br><span class="line"><span class="comment">** crypto-js </span></span><br><span class="line"><span class="comment">** word：待加密或者解密的字符串</span></span><br><span class="line"><span class="comment">** keyStr：AES 加密需要用到的16位字符串的key</span></span><br><span class="line"><span class="comment">*/</span></span><br><span class="line"><span class="keyword">import</span> <span class="title class_">CryptoJS</span> <span class="keyword">from</span> <span class="string">&#x27;crypto-js&#x27;</span></span><br><span class="line"><span class="keyword">export</span> <span class="keyword">const</span> crypto = &#123;</span><br><span class="line">  <span class="attr">aesKey</span>: <span class="string">&#x27;com.iescp.gate&#x27;</span>,</span><br><span class="line">  <span class="title class_">AESEnc</span> (content, key) &#123;</span><br><span class="line">    key = key || <span class="variable language_">this</span>.<span class="property">aesKey</span>;</span><br><span class="line">    key = <span class="title class_">CryptoJS</span>.<span class="property">enc</span>.<span class="property">Utf8</span>.<span class="title function_">parse</span>(key) <span class="comment">// 加密密钥</span></span><br><span class="line">    <span class="keyword">var</span> srcs = <span class="title class_">CryptoJS</span>.<span class="property">enc</span>.<span class="property">Utf8</span>.<span class="title function_">parse</span>(content)</span><br><span class="line">    <span class="keyword">var</span> encrypted = <span class="title class_">CryptoJS</span>.<span class="property">AES</span>.<span class="title function_">encrypt</span>(srcs, key, &#123; </span><br><span class="line">      <span class="attr">iv</span>: key, </span><br><span class="line">      <span class="attr">mode</span>: <span class="title class_">CryptoJS</span>.<span class="property">mode</span>.<span class="property">CBC</span> </span><br><span class="line">    &#125;)</span><br><span class="line">    <span class="keyword">return</span> encrypted.<span class="title function_">toString</span>();</span><br><span class="line">  &#125;,</span><br><span class="line">  <span class="title class_">AESDec</span>: <span class="keyword">function</span> (<span class="params">content, key</span>) &#123;</span><br><span class="line">    key = key || <span class="variable language_">this</span>.<span class="property">aesKey</span>;</span><br><span class="line">    key = <span class="title class_">CryptoJS</span>.<span class="property">enc</span>.<span class="property">Utf8</span>.<span class="title function_">parse</span>(key) <span class="comment">// 解密密钥</span></span><br><span class="line">    <span class="keyword">let</span> decrypted = <span class="title class_">CryptoJS</span>.<span class="property">AES</span>.<span class="title function_">decrypt</span>(content, key, &#123; </span><br><span class="line">      <span class="attr">iv</span>: key, </span><br><span class="line">      <span class="attr">mode</span>: <span class="title class_">CryptoJS</span>.<span class="property">mode</span>.<span class="property">CBC</span> </span><br><span class="line">    &#125;)</span><br><span class="line">    <span class="keyword">let</span> decryptedStr = decrypted.<span class="title function_">toString</span>(<span class="title class_">CryptoJS</span>.<span class="property">enc</span>.<span class="property">Utf8</span>)</span><br><span class="line">    <span class="keyword">return</span> decryptedStr;</span><br><span class="line">  &#125;</span><br><span class="line">&#125; </span><br></pre></td></tr></table></figure>


<h1 id="五、状态管理-Vuex"><a href="#五、状态管理-Vuex" class="headerlink" title="五、状态管理 Vuex"></a>五、状态管理 Vuex</h1><h2 id="核心概念"><a href="#核心概念" class="headerlink" title="核心概念"></a>核心概念</h2><blockquote>
<p>本质是一个挂载到 vue 实例的全局变量对象 store，它的属性和方法负责管理所有组件的状态及其更新。</p>
</blockquote>
<ul>
<li><strong>state</strong>：包含所有应用级别状态的对象 (组件用到的数据)。</li>
<li><strong>getters</strong>：派生出 state 所需数据 (计算属性)。</li>
<li><strong>mutators</strong>：更新 state 的唯一方式 (同步更新)。</li>
<li><strong>actions</strong>：异步提交 mutaions 更新状态 (异步更新)。</li>
<li><strong>module</strong>：划分为不同模块管理 (方便维护大型项目)。</li>
</ul>
<h2 id="主要特点"><a href="#主要特点" class="headerlink" title="主要特点"></a>主要特点</h2><ul>
<li>只能应用于 Vue，通过响应式机制更新视图。</li>
<li>单一数据源：全局只有一个 Store 实例。</li>
<li>单向数据流：<code>View、Action、Mutation、State</code>。</li>
</ul>
  <div align="center">
      <img src="" data-original="/images/frame/vuex_base.png" alt="Vuex 单向数据流" width="100%">
  </div>
          
      
<h2 id="目录结构"><a href="#目录结构" class="headerlink" title="目录结构"></a>目录结构</h2><blockquote>
<p>如果 store 文件太大则需要分割到单独文件。</p>
</blockquote>
  <figure class="highlight js"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br></pre></td><td class="code"><pre><span class="line">store</span><br><span class="line">  ├── index.<span class="property">js</span>         <span class="comment">// 组装模块并导出store </span></span><br><span class="line">  ├── actions.<span class="property">js</span>       <span class="comment">// 根级别的 action</span></span><br><span class="line">  ├── mutations.<span class="property">js</span>     <span class="comment">// 根级别的 mutation</span></span><br><span class="line">  └── modules          <span class="comment">// 大型应用时分割到模块</span></span><br><span class="line">      ├── cart.<span class="property">js</span>      <span class="comment">// 购物车模块</span></span><br><span class="line">      └── products.<span class="property">js</span>  <span class="comment">// 产品模块</span></span><br></pre></td></tr></table></figure>


<h2 id="自定义配置-1"><a href="#自定义配置-1" class="headerlink" title="自定义配置"></a>自定义配置</h2><h3 id="单个文件"><a href="#单个文件" class="headerlink" title="单个文件"></a>单个文件</h3>  <figure class="highlight js"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br><span class="line">42</span><br><span class="line">43</span><br><span class="line">44</span><br><span class="line">45</span><br><span class="line">46</span><br><span class="line">47</span><br><span class="line">48</span><br><span class="line">49</span><br><span class="line">50</span><br><span class="line">51</span><br><span class="line">52</span><br><span class="line">53</span><br><span class="line">54</span><br><span class="line">55</span><br><span class="line">56</span><br><span class="line">57</span><br><span class="line">58</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">// vuex/store.js</span></span><br><span class="line"></span><br><span class="line"><span class="keyword">import</span> <span class="title class_">Vue</span> <span class="keyword">from</span> <span class="string">&quot;vue&quot;</span>;</span><br><span class="line"><span class="keyword">import</span> <span class="title class_">Vuex</span> <span class="keyword">from</span> <span class="string">&quot;vuex&quot;</span>;</span><br><span class="line"></span><br><span class="line"><span class="title class_">Vue</span>.<span class="title function_">use</span>(<span class="title class_">Vuex</span>);</span><br><span class="line"></span><br><span class="line"><span class="keyword">export</span> <span class="keyword">default</span> <span class="keyword">new</span> <span class="title class_">Vuex</span>.<span class="title class_">Store</span>(&#123;</span><br><span class="line">  <span class="comment">// state 状态变量</span></span><br><span class="line">  <span class="attr">state</span>: &#123;</span><br><span class="line">    <span class="attr">VIEWID</span>: <span class="number">0</span>,</span><br><span class="line">    <span class="attr">LOADING</span>: &#123;</span><br><span class="line">      <span class="attr">status</span>: <span class="number">0</span>,</span><br><span class="line">      <span class="attr">msg</span>: <span class="string">&quot;&quot;</span></span><br><span class="line">    &#125;</span><br><span class="line">  &#125;,</span><br><span class="line">  <span class="comment">// state 的计算属性：派生所需状态</span></span><br><span class="line">  <span class="attr">getters</span>: &#123;</span><br><span class="line">    <span class="title class_">IDNew</span>: <span class="function"><span class="params">state</span> =&gt;</span> &#123;  </span><br><span class="line">      <span class="keyword">return</span> state.<span class="property">ID</span> * <span class="number">10</span>;</span><br><span class="line">    &#125;</span><br><span class="line">  &#125;,</span><br><span class="line">  <span class="comment">// 同步更新 state：store.commit(&#x27;showLoad&#x27;, &#123; status: 1, msg: &quot;&quot; &#125;)</span></span><br><span class="line">  <span class="attr">mutations</span>: &#123;</span><br><span class="line">    <span class="title function_">viewEntrance</span>(<span class="params">state, id</span>)&#123;</span><br><span class="line">      state.<span class="property">VIEWID</span> = id</span><br><span class="line">    &#125;,</span><br><span class="line">    showLoad (state, obj)&#123;</span><br><span class="line">      state.<span class="property">LOADING</span> = obj</span><br><span class="line">    &#125;,</span><br><span class="line">    hideLoad (state)&#123;</span><br><span class="line">      state.<span class="property">LOADING</span> = &#123; <span class="attr">status</span>: <span class="number">0</span>, <span class="attr">msg</span>: <span class="string">&quot;&quot;</span> &#125;</span><br><span class="line">    &#125;</span><br><span class="line">  &#125;,</span><br><span class="line">  <span class="comment">// 异步更新 state：this.$store.dispatch(&#x27;viewEntrance&#x27;, id)</span></span><br><span class="line">  <span class="attr">actions</span>: &#123;</span><br><span class="line">    <span class="comment">// 简写写法</span></span><br><span class="line">    <span class="attr">viewEntrance</span>: <span class="function">(<span class="params">&#123; commit &#125;, id</span>) =&gt;</span> <span class="title function_">commit</span>(<span class="string">&#x27;viewEntrance&#x27;</span>, id),</span><br><span class="line">    <span class="comment">// 完整写法</span></span><br><span class="line">    <span class="attr">viewEntrance</span>: <span class="function">(<span class="params"> context, id</span>) =&gt;</span> &#123; context.<span class="title function_">commit</span>(<span class="string">&#x27;viewEntrance&#x27;</span>, id) &#125;,</span><br><span class="line">    <span class="comment">// 异步操作</span></span><br><span class="line">    <span class="attr">entryAsync</span>: <span class="function">(<span class="params">&#123; commit &#125;, id</span>) =&gt;</span> &#123;  </span><br><span class="line">      <span class="built_in">setTimeout</span> (<span class="function">() =&gt;</span> &#123;</span><br><span class="line">          <span class="title function_">commit</span>(<span class="string">&#x27;viewEntrance&#x27;</span>, id)</span><br><span class="line">      &#125;, <span class="number">1000</span>);</span><br><span class="line">    &#125;</span><br><span class="line">  &#125;,</span><br><span class="line">  <span class="comment">// 分割成不同模块以方便管理：使用时不再导出以上变量</span></span><br><span class="line">  <span class="attr">modules</span>: &#123;</span><br><span class="line">    <span class="attr">a</span>: &#123;</span><br><span class="line">      <span class="attr">state</span>: &#123;&#125;,</span><br><span class="line">      <span class="attr">getters</span>: &#123;&#125;,</span><br><span class="line">      <span class="attr">mutations</span>: &#123;&#125;,</span><br><span class="line">      <span class="attr">actions</span>: &#123;&#125;,</span><br><span class="line">    &#125;,</span><br><span class="line">    <span class="attr">b</span>: &#123;&#125;</span><br><span class="line">  &#125;</span><br><span class="line">&#125;)</span><br></pre></td></tr></table></figure>
<h2 id="全局引用"><a href="#全局引用" class="headerlink" title="全局引用"></a>全局引用</h2>  <figure class="highlight js"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">// main.js</span></span><br><span class="line"><span class="keyword">import</span> store <span class="keyword">from</span> <span class="string">&#x27;./vuex&#x27;</span>  </span><br><span class="line"><span class="keyword">new</span> <span class="title class_">Vue</span>(&#123;</span><br><span class="line">  <span class="attr">el</span>: <span class="string">&#x27;#app&#x27;</span>,</span><br><span class="line">  router,</span><br><span class="line">  store,</span><br><span class="line">&#125;)</span><br></pre></td></tr></table></figure>


<h2 id="组件使用"><a href="#组件使用" class="headerlink" title="组件使用"></a>组件使用</h2>  <figure class="highlight js"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br><span class="line">42</span><br><span class="line">43</span><br><span class="line">44</span><br><span class="line">45</span><br><span class="line">46</span><br><span class="line">47</span><br><span class="line">48</span><br><span class="line">49</span><br><span class="line">50</span><br><span class="line">51</span><br><span class="line">52</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">import</span> &#123; mapState, mapGetters, mapMutations, mapActions &#125; <span class="keyword">from</span> <span class="string">&#x27;vuex&#x27;</span></span><br><span class="line"><span class="keyword">export</span> <span class="keyword">default</span> &#123;</span><br><span class="line">  <span class="title function_">data</span>(<span class="params"></span>)&#123;</span><br><span class="line">      <span class="keyword">return</span>&#123;</span><br><span class="line">          <span class="attr">localState</span>: <span class="number">2</span></span><br><span class="line">      &#125;</span><br><span class="line">  &#125;,</span><br><span class="line">  <span class="comment">// 普通写法</span></span><br><span class="line">  <span class="attr">computed</span>: &#123;     </span><br><span class="line">      count () &#123;</span><br><span class="line">          <span class="keyword">return</span> <span class="variable language_">this</span>.<span class="property">$store</span>.<span class="property">state</span>.<span class="property">count</span>;</span><br><span class="line">      &#125;,</span><br><span class="line">      <span class="title function_">isShow</span>(<span class="params"></span>)&#123;</span><br><span class="line">          <span class="keyword">return</span> <span class="variable language_">this</span>.<span class="property">$store</span>.<span class="property">state</span>.<span class="property">isShow</span>;</span><br><span class="line">      &#125;</span><br><span class="line">  &#125;,</span><br><span class="line">  <span class="comment">// 简洁写法：使用辅助函数返回对象并映射到组件实例</span></span><br><span class="line">  <span class="attr">computed</span>: <span class="title function_">mapState</span>(&#123;  </span><br><span class="line">      <span class="attr">count</span>: <span class="function"><span class="params">state</span> =&gt;</span> state.<span class="property">count</span>, </span><br><span class="line">      <span class="attr">countAlias</span>: <span class="string">&#x27;count&#x27;</span>,      <span class="comment">// 改变名称</span></span><br><span class="line">      <span class="title function_">countPlus</span>(<span class="params">state</span>)&#123;         <span class="comment">// 使this指向组件对象</span></span><br><span class="line">          <span class="keyword">return</span> state.<span class="property">count</span> + <span class="variable language_">this</span>.<span class="property">localState</span>; </span><br><span class="line">      &#125;,</span><br><span class="line">  &#125;),</span><br><span class="line">  <span class="attr">computed</span>: <span class="title function_">mapState</span>([<span class="string">&#x27;count&#x27;</span>, <span class="string">&#x27;isShow&#x27;</span>]),  <span class="comment">// 名称相同</span></span><br><span class="line">  <span class="attr">computed</span>: &#123;</span><br><span class="line">    <span class="title function_">local</span>(<span class="params"></span>)&#123;         <span class="comment">// 组件数据</span></span><br><span class="line">      <span class="keyword">return</span> <span class="variable language_">this</span>.<span class="property">localState</span>;</span><br><span class="line">    &#125;,</span><br><span class="line">    <span class="comment">// 使用对象展开运算符将数据混入 computed 对象</span></span><br><span class="line">    ...<span class="title function_">mapState</span>([    <span class="comment">// 映射 State</span></span><br><span class="line">      <span class="string">&#x27;count&#x27;</span>,</span><br><span class="line">      <span class="string">&#x27;isShow&#x27;</span></span><br><span class="line">    ]),</span><br><span class="line">    ...<span class="title function_">mapGetters</span>([  <span class="comment">// 映射 Getters </span></span><br><span class="line">      <span class="string">&#x27;countNew&#x27;</span></span><br><span class="line">    ])</span><br><span class="line">  &#125;, </span><br><span class="line">  <span class="attr">methods</span>: &#123;   </span><br><span class="line">    <span class="title function_">reduce</span>(<span class="params"></span>)&#123;     <span class="comment">// 有参数时需单独定义</span></span><br><span class="line">      <span class="variable language_">this</span>.<span class="property">$store</span>.<span class="title function_">commit</span>(<span class="string">&#x27;add&#x27;</span>)           <span class="comment">// 同步</span></span><br><span class="line">      <span class="variable language_">this</span>.<span class="property">$store</span>.<span class="title function_">dispatch</span>(<span class="string">&#x27;reduce&#x27;</span>, <span class="number">2</span>)   <span class="comment">// 异步</span></span><br><span class="line">    &#125;,</span><br><span class="line">    ...<span class="title function_">mapActions</span>([  <span class="comment">// 映射 Mutations</span></span><br><span class="line">      <span class="string">&#x27;add&#x27;</span>,  </span><br><span class="line">      <span class="string">&#x27;tog&#x27;</span>,</span><br><span class="line">      <span class="string">&#x27;addAsync&#x27;</span></span><br><span class="line">    ])</span><br><span class="line">  &#125;,</span><br><span class="line">  <span class="attr">methods</span>: <span class="title function_">mapActions</span>([<span class="string">&#x27;add&#x27;</span>])</span><br><span class="line">  <span class="attr">methods</span>: <span class="title function_">mapMutations</span>([<span class="string">&#x27;add&#x27;</span>])</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>


<h2 id="简单用法"><a href="#简单用法" class="headerlink" title="简单用法"></a>简单用法</h2>  <figure class="highlight js"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">// store.js</span></span><br><span class="line"><span class="keyword">export</span> <span class="keyword">default</span> <span class="keyword">new</span> <span class="title class_">Vuex</span>.<span class="title class_">Store</span>(&#123;</span><br><span class="line">  <span class="attr">state</span>: &#123;</span><br><span class="line">    <span class="attr">LOADING</span>: <span class="literal">false</span></span><br><span class="line">  &#125;,</span><br><span class="line">  <span class="attr">mutations</span>: &#123;</span><br><span class="line">    <span class="title function_">setState</span>(<span class="params">state, newState</span>) &#123;</span><br><span class="line">      <span class="title class_">Object</span>.<span class="title function_">assign</span>(state, newState)</span><br><span class="line">    &#125;</span><br><span class="line">  &#125;,</span><br><span class="line">  <span class="attr">actions</span>: &#123; &#125;</span><br><span class="line">&#125;)</span><br><span class="line"></span><br><span class="line"><span class="comment">// main.js</span></span><br><span class="line"><span class="title class_">Object</span>.<span class="title function_">assign</span>(<span class="title class_">Vue</span>.<span class="property"><span class="keyword">prototype</span></span>, &#123;</span><br><span class="line">  <span class="attr">showLoading</span>: <span class="keyword">function</span> (<span class="params"></span>) &#123;</span><br><span class="line">    store.<span class="title function_">commit</span>(<span class="string">&#x27;setState&#x27;</span>, &#123; <span class="attr">LOADING</span>: <span class="literal">true</span> &#125;)</span><br><span class="line">  &#125;,</span><br><span class="line">  <span class="title function_">hideLoading</span>(<span class="params"></span>) &#123;</span><br><span class="line">    store.<span class="title function_">commit</span>(<span class="string">&#x27;setState&#x27;</span>, &#123; <span class="attr">LOADING</span>: <span class="literal">false</span> &#125;)</span><br><span class="line">  &#125;</span><br><span class="line">&#125;)</span><br><span class="line"></span><br><span class="line"><span class="comment">// 组件中使用</span></span><br><span class="line"><span class="variable language_">this</span>.<span class="title function_">showLoading</span>()</span><br><span class="line"><span class="variable language_">this</span>.<span class="title function_">hideLoading</span>()</span><br></pre></td></tr></table></figure>


<h1 id="六、组件化开发"><a href="#六、组件化开发" class="headerlink" title="六、组件化开发"></a>六、组件化开发</h1><h2 id="组件实例化"><a href="#组件实例化" class="headerlink" title="组件实例化"></a>组件实例化</h2><blockquote>
<p>组件只有挂载到某个 Vue 实例下才会生效，挂载的本质就是创建一个包含数据、方法和组件的 vue 实例对象。</p>
</blockquote>
  <figure class="highlight js"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">// 1、直接创建</span></span><br><span class="line"><span class="keyword">var</span> app1 = <span class="keyword">new</span> <span class="title class_">Vue</span>(&#123;</span><br><span class="line">  <span class="attr">el</span>: <span class="string">&quot;#app1&quot;</span>,</span><br><span class="line">  <span class="attr">data</span>: &#123;&#125;</span><br><span class="line">&#125;)</span><br><span class="line"></span><br><span class="line"><span class="comment">// 2、首先创建无挂载点的实例</span></span><br><span class="line"><span class="keyword">var</span> app2 = <span class="keyword">new</span> <span class="title class_">Vue</span>(&#123;    </span><br><span class="line">  <span class="attr">data</span>: &#123;          <span class="comment">// 对象</span></span><br><span class="line">    <span class="attr">msg</span>: <span class="string">&quot;app2&quot;</span> </span><br><span class="line">  &#125;</span><br><span class="line">&#125;)</span><br><span class="line">app2.$mount(<span class="string">&#x27;#app2&#x27;</span>);</span><br><span class="line"></span><br><span class="line"><span class="comment">// 3、使用基础 Vue 构造器创建子类</span></span><br><span class="line"><span class="keyword">var</span> app3 = <span class="title class_">Vue</span>.<span class="title function_">extend</span>(&#123;</span><br><span class="line">  <span class="attr">data</span>: <span class="keyword">function</span>(<span class="params"></span>)&#123;   <span class="comment">// 函数</span></span><br><span class="line">    <span class="keyword">return</span>&#123; </span><br><span class="line">      <span class="attr">msg</span>:<span class="string">&quot;app3&quot;</span> </span><br><span class="line">    &#125;</span><br><span class="line">  &#125;</span><br><span class="line">&#125;)    </span><br><span class="line"><span class="keyword">new</span> <span class="title function_">app3</span>().$mount(<span class="string">&#x27;#app3&#x27;</span>);</span><br></pre></td></tr></table></figure>


<h2 id="组件定义"><a href="#组件定义" class="headerlink" title="组件定义"></a>组件定义</h2><blockquote>
<p>三种书写方式：<strong>单文件组件</strong>、<strong>template 标签</strong>、<strong>script 标签</strong>。组件必须注册才能生效。组件和指令命名时注意：不能使用标签和关键字、尽量不使用驼峰命名 (因为 webpack 编译后会统一变为小写)，如果有大写字母则使用时必须都改为小写并添加 <code>-、v-</code>。</p>
</blockquote>
  <figure class="highlight js"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br><span class="line">42</span><br><span class="line">43</span><br><span class="line">44</span><br><span class="line">45</span><br><span class="line">46</span><br><span class="line">47</span><br><span class="line">48</span><br><span class="line">49</span><br><span class="line">50</span><br><span class="line">51</span><br><span class="line">52</span><br><span class="line">53</span><br><span class="line">54</span><br><span class="line">55</span><br><span class="line">56</span><br><span class="line">57</span><br><span class="line">58</span><br><span class="line">59</span><br><span class="line">60</span><br><span class="line">61</span><br><span class="line">62</span><br><span class="line">63</span><br><span class="line">64</span><br><span class="line">65</span><br><span class="line">66</span><br><span class="line">67</span><br><span class="line">68</span><br><span class="line">69</span><br><span class="line">70</span><br><span class="line">71</span><br><span class="line">72</span><br><span class="line">73</span><br><span class="line">74</span><br><span class="line">75</span><br><span class="line">76</span><br><span class="line">77</span><br><span class="line">78</span><br><span class="line">79</span><br><span class="line">80</span><br><span class="line">81</span><br><span class="line">82</span><br><span class="line">83</span><br><span class="line">84</span><br><span class="line">85</span><br><span class="line">86</span><br><span class="line">87</span><br><span class="line">88</span><br><span class="line">89</span><br><span class="line">90</span><br><span class="line">91</span><br><span class="line">92</span><br><span class="line">93</span><br><span class="line">94</span><br><span class="line">95</span><br><span class="line">96</span><br><span class="line">97</span><br><span class="line">98</span><br><span class="line">99</span><br><span class="line">100</span><br><span class="line">101</span><br><span class="line">102</span><br><span class="line">103</span><br><span class="line">104</span><br><span class="line">105</span><br><span class="line">106</span><br><span class="line">107</span><br><span class="line">108</span><br><span class="line">109</span><br><span class="line">110</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">// 单文件组件配置选项：扩展名为 vue</span></span><br><span class="line"><span class="keyword">var</span> myMixin = </span><br><span class="line"><span class="keyword">export</span> <span class="keyword">default</span> &#123;</span><br><span class="line">  <span class="attr">mixins</span>: [        <span class="comment">// 混入：扩展组件功能，可看作继承。</span></span><br><span class="line">    &#123;</span><br><span class="line">      <span class="title function_">data</span>(<span class="params"></span>)&#123;</span><br><span class="line">        <span class="keyword">return</span> &#123;</span><br><span class="line">          <span class="attr">msg</span>:<span class="string">&#x27;mixins:msg&#x27;</span>,</span><br><span class="line">          <span class="attr">name</span>:<span class="string">&#x27;mixins:name&#x27;</span></span><br><span class="line">        &#125;</span><br><span class="line">      &#125;,</span><br><span class="line">      <span class="attr">methods</span>: &#123;</span><br><span class="line">        <span class="title function_">hello</span>(<span class="params"></span>) &#123;</span><br><span class="line">          <span class="variable language_">console</span>.<span class="title function_">log</span>(<span class="string">&#x27;mixin:hello&#x27;</span>)</span><br><span class="line">        &#125;</span><br><span class="line">      &#125;,</span><br><span class="line">      <span class="title function_">created</span>(<span class="params"></span>) &#123;</span><br><span class="line">        <span class="variable language_">this</span>.<span class="title function_">hello</span>()</span><br><span class="line">      &#125;</span><br><span class="line">    &#125;</span><br><span class="line">  ],</span><br><span class="line">  <span class="attr">directive</span>: &#123;</span><br><span class="line">    <span class="comment">// 注册一个局部的自定义指令 v-auto-focus</span></span><br><span class="line">    <span class="attr">autoFocus</span>: &#123;</span><br><span class="line">      <span class="title function_">bind</span>(<span class="params">el, binding, vnode</span>)&#123; </span><br><span class="line">        <span class="comment">// 创建：指令第一次绑定到元素时调用，比如添加事件监听器等</span></span><br><span class="line">      &#125;,      </span><br><span class="line">      <span class="title function_">inserted</span>(<span class="params">el</span>)&#123;    </span><br><span class="line">        el.<span class="title function_">focus</span>()</span><br><span class="line">        <span class="comment">// 插入：当元素被插入到 DOM</span></span><br><span class="line">      &#125;,      </span><br><span class="line">      <span class="title function_">update</span>(<span class="params">el, binding, vnode, oldVnode</span>)&#123; </span><br><span class="line">        <span class="comment">// 更新：当元素所在模板更新时</span></span><br><span class="line">      &#125;,     </span><br><span class="line">      <span class="title function_">componentUpdate</span>(<span class="params">el, binding, vnode, oldVnode</span>)&#123; </span><br><span class="line">        <span class="comment">// 当元素所在模板完成一次更新周期时</span></span><br><span class="line">      &#125;,   </span><br><span class="line">      <span class="title function_">unbind</span>(<span class="params">el, binding, vnode</span>)&#123;          </span><br><span class="line">        <span class="comment">// 解除绑定时只调用一次，比如移除 bind 时绑定的事件监听器</span></span><br><span class="line">      &#125;</span><br><span class="line">    &#125;</span><br><span class="line">  &#125;,</span><br><span class="line">  <span class="attr">filters</span>: &#123;          <span class="comment">// 过滤器：&#123;&#123;user.age | sum&#125;&#125; </span></span><br><span class="line">    sum (value) &#123;</span><br><span class="line">      <span class="keyword">return</span> value == <span class="number">0</span>;</span><br><span class="line">    &#125;</span><br><span class="line">  &#125;,</span><br><span class="line">  <span class="attr">components</span>: &#123; <span class="comment">// 组件注册：使用时 &lt;my-com&gt;</span></span><br><span class="line">    <span class="title class_">MyCom</span> </span><br><span class="line">  &#125;,</span><br><span class="line">  <span class="title function_">data</span>(<span class="params"></span>)&#123;      <span class="comment">// 组件数据：组件内必须使用箭头函数，否则 this 不指向当前组件</span></span><br><span class="line">    <span class="keyword">return</span> &#123;</span><br><span class="line">      <span class="attr">name</span>: <span class="string">&quot;tom&quot;</span></span><br><span class="line">      <span class="attr">age</span>: <span class="number">20</span></span><br><span class="line">    &#125;</span><br><span class="line">  &#125;,</span><br><span class="line">  <span class="attr">computed</span>: &#123; &#125;,   <span class="comment">// 计算属性：派生所需数据</span></span><br><span class="line">  <span class="attr">methods</span>: &#123; &#125;,    <span class="comment">// 事件绑定：事件名不区分大小写)</span></span><br><span class="line">  <span class="attr">watch</span>:&#123;          <span class="comment">// 监听数据</span></span><br><span class="line">    <span class="attr">user</span>: &#123;        <span class="comment">// 深度监听(可监听到对象内部属性变化)</span></span><br><span class="line">      <span class="attr">handler</span>: <span class="string">&#x27;getList&#x27;</span>,</span><br><span class="line">      <span class="attr">immediate</span>: <span class="literal">true</span>,</span><br><span class="line"></span><br><span class="line">      <span class="title function_">handler</span>(<span class="params">val, oldval</span>)&#123; &#125;,</span><br><span class="line">      <span class="attr">deep</span>: <span class="literal">true</span>,</span><br><span class="line">    &#125;,  </span><br><span class="line">    <span class="string">&quot;user.name&quot;</span>: <span class="keyword">function</span>(<span class="params">val, oldval</span>)&#123; <span class="comment">// 必须加引号  </span></span><br><span class="line">      <span class="variable language_">console</span>.<span class="title function_">log</span>(val)  </span><br><span class="line">    &#125;,</span><br><span class="line">    $route(to, <span class="keyword">from</span>)&#123;            <span class="comment">// 监听子组件路由变化</span></span><br><span class="line">      <span class="variable language_">console</span>.<span class="title function_">log</span>(to.<span class="property">name</span>)</span><br><span class="line">    &#125;</span><br><span class="line">  &#125;,</span><br><span class="line">  mounted () &#123;    <span class="comment">// 生命周期</span></span><br><span class="line">    <span class="variable language_">this</span>.<span class="property">$root</span>.<span class="property">eventHub</span>.$on(<span class="string">&#x27;updateDash&#x27;</span>, <span class="variable language_">this</span>.<span class="property">getList</span>)</span><br><span class="line">    <span class="variable language_">window</span>.<span class="title function_">addEventListener</span>(<span class="string">&#x27;scroll&#x27;</span>, <span class="variable language_">this</span>.<span class="property">handleScroll</span>)</span><br><span class="line">    <span class="comment">// 推迟回调到下次 DOM 更新循环之后执行</span></span><br><span class="line">    <span class="variable language_">this</span>.$nextTick(<span class="function">() =&gt;</span> &#123;</span><br><span class="line">      <span class="variable language_">console</span>.<span class="title function_">log</span>(<span class="number">444</span>);</span><br><span class="line">      <span class="variable language_">console</span>.<span class="title function_">log</span>(<span class="variable language_">this</span>.<span class="property">$refs</span>[<span class="string">&#x27;hello&#x27;</span>]);</span><br><span class="line">    &#125;);</span><br><span class="line">  &#125;,</span><br><span class="line">  <span class="title function_">beforeDestroy</span>(<span class="params"></span>)&#123;</span><br><span class="line">    <span class="variable language_">this</span>.<span class="property">$root</span>.<span class="property">eventHub</span>.$off(<span class="string">&#x27;updateDash&#x27;</span>)</span><br><span class="line">    <span class="variable language_">window</span>.<span class="title function_">removeEventListener</span>(<span class="string">&#x27;scroll&#x27;</span>, <span class="variable language_">this</span>.<span class="property">handleScroll</span>)</span><br><span class="line">  &#125;   </span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line"><span class="comment">// 全局</span></span><br><span class="line"><span class="title class_">Vue</span>.<span class="title function_">component</span>(<span class="string">&#x27;myCom&#x27;</span>, &#123; &#125;)</span><br><span class="line"></span><br><span class="line"><span class="title class_">Vue</span>.<span class="title function_">use</span>(<span class="title class_">MyPlugin</span>, &#123; <span class="attr">someOption</span>: <span class="literal">true</span> &#125;)</span><br><span class="line"></span><br><span class="line"><span class="title class_">Object</span>.<span class="title function_">assign</span>(<span class="title class_">Vue</span>.<span class="property"><span class="keyword">prototype</span></span>, &#123;</span><br><span class="line">  showLoading () &#123;</span><br><span class="line">    store.<span class="title function_">commit</span>(<span class="string">&#x27;setState&#x27;</span>, &#123; <span class="attr">LOADING</span>: <span class="literal">true</span> &#125;)</span><br><span class="line">  &#125;,</span><br><span class="line">  <span class="title function_">hideLoading</span>(<span class="params"></span>) &#123;</span><br><span class="line">    store.<span class="title function_">commit</span>(<span class="string">&#x27;setState&#x27;</span>, &#123; <span class="attr">LOADING</span>: <span class="literal">false</span> &#125;)</span><br><span class="line">  &#125;</span><br><span class="line">&#125;)</span><br><span class="line"><span class="title class_">Vue</span>.<span class="title function_">directive</span>(<span class="string">&quot;autoFocus &quot;</span>, &#123;</span><br><span class="line">  <span class="title function_">inserted</span>(<span class="params">el</span>)&#123;  el.<span class="title function_">focus</span>() &#125;</span><br><span class="line">&#125;)</span><br><span class="line"></span><br><span class="line"><span class="title class_">Vue</span>.<span class="title function_">filter</span>(<span class="string">&#x27;formatDate&#x27;</span>, <span class="keyword">function</span> (<span class="params">value, fmt</span>)&#123;&#125;)</span><br><span class="line"></span><br><span class="line"><span class="title class_">Vue</span>.<span class="title function_">mixin</span>(&#123;&#125;)</span><br><span class="line"></span><br><span class="line"><span class="title class_">Vue</span>.<span class="title function_">nextTick</span>()</span><br></pre></td></tr></table></figure>


<h2 id="生命周期"><a href="#生命周期" class="headerlink" title="生命周期"></a>生命周期</h2><blockquote>
<p>Vue 实例由创建到销毁的完整运行一次的过程中会触发的函数。</p>
</blockquote>
<ul>
<li><strong>beforeCreate</strong>：初始化非响应式变量，比如添加 Loading。</li>
<li><strong>created</strong>：页面初始化，比如关闭 Loading 和 Ajax 请求。</li>
<li><strong>mounted</strong>：获取和操作 Dom 元素和 Ajax 请求。</li>
<li><strong>updated</strong>：统一处理数据，但可能陷入死循环。</li>
<li><strong>beforeDestroy</strong>：销毁定时器、解绑全局事件、销毁插件对象等操作。</li>
</ul>
  <div align="center">
      <img src="" data-original="/images/frame/vue_life.png" alt="Vue 生命周期" width="100%">
  </div>


<h2 id="内置指令"><a href="#内置指令" class="headerlink" title="内置指令"></a>内置指令</h2><ul>
<li>数据渲染：<code>双层 &#123; &#125;、v-text、v-html</code></li>
<li>条件渲染：<code>v-if、v-else</code></li>
<li>循环渲染：<ul>
<li>数组：<code>v-for=&quot;(item, index) in arr&quot; :key=&quot;index&quot;</code></li>
<li>对象：<code>v-for=&quot;(item, key, index) of obj&quot; :key=&quot;index&quot;</code></li>
</ul>
</li>
<li>事件绑定：<code>v-on:</code> 可缩写为 <code>@</code>。<ul>
<li>绑定：<code>v-on:click = &quot;todo&quot;、@click = &quot;todo&quot;</code></li>
<li>修饰符：<code>@click.stop.self、@keyup.stop.enter</code>。阻止冒泡 stop、阻止默认 prevent、执行一次 once。</li>
</ul>
</li>
<li>动态绑定：<code>v-bind:</code>，注意可以省略 v-bind <ul>
<li>class：<code>:class=&quot; [&#39;a&#39;, &#39;b&#39;]、[ true ? &#39;a&#39;: &#39;b&#39;]、&#123; &#39;active&#39;: isActive(id) &#125; &quot;</code>。</li>
<li>style：<code>:style=&quot;&#123;color: &#39;red&#39;&#125;、[&#123;color: &#39;red&#39;&#125;, &#123;fontSize: &#39;16px&#39;&#125;]&quot;</code>。</li>
</ul>
</li>
<li>双向绑定<ul>
<li>绑定：<code>v-model、v-model.trim</code></li>
<li>修饰符：trim 首尾空格过滤、lazy 监听change事件、number 字符串转为数字。</li>
</ul>
</li>
<li>性能优化<ul>
<li>只渲染一次：<code>v-once</code></li>
<li>防止页面闪烁：<code>v-cloak</code></li>
<li>不输出 data：<code>v-pre</code></li>
</ul>
</li>
</ul>
<h2 id="组件通信"><a href="#组件通信" class="headerlink" title="组件通信"></a>组件通信</h2><h3 id="父子组件"><a href="#父子组件" class="headerlink" title="父子组件"></a>父子组件</h3><ul>
<li>子传父：父组件监听 <code>&lt;child @updateList = &quot;updateList&quot;&gt;&lt;/child&gt;</code>，子组件触发自定义事件 <code>this.$emit(&quot;updateList&quot;, data)</code>。</li>
<li>父传子：在子组件中通过 props 定义父组件传递的属性如下：  <figure class="highlight js"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">// 父组件：&lt;child name=&quot;Tom&quot; :songs=&quot;songs&quot; :age=&quot;age&quot;&gt;&lt;/child&gt;</span></span><br><span class="line"><span class="keyword">export</span> <span class="keyword">default</span> &#123;</span><br><span class="line">  <span class="comment">// 简洁写法</span></span><br><span class="line">  <span class="attr">props</span>: [<span class="string">&quot;name&quot;</span>, <span class="string">&quot;songs&quot;</span>]</span><br><span class="line"></span><br><span class="line">  <span class="comment">// 普通写法</span></span><br><span class="line">  <span class="attr">props</span>: &#123;</span><br><span class="line">    <span class="attr">name</span>:&#123;  <span class="comment">// 静态数据</span></span><br><span class="line">      <span class="attr">type</span>: <span class="title class_">String</span></span><br><span class="line">    &#125;</span><br><span class="line">    <span class="attr">songs</span>:&#123;  <span class="comment">// 动态数据</span></span><br><span class="line">      <span class="attr">type</span>: <span class="title class_">Array</span></span><br><span class="line">    &#125;,</span><br><span class="line">    <span class="attr">age</span>:&#123;     <span class="comment">// 动态数据验证</span></span><br><span class="line">      <span class="attr">type</span>: <span class="title class_">Number</span>,   </span><br><span class="line">      <span class="attr">required</span>: <span class="literal">true</span>,</span><br><span class="line">      <span class="comment">// default: 1000,</span></span><br><span class="line">      <span class="title function_">default</span>(<span class="params"></span>)&#123;     <span class="comment">// 默认值, 可直接1000 </span></span><br><span class="line">        <span class="keyword">return</span> &#123; <span class="attr">time</span>: <span class="number">1000</span> &#125; </span><br><span class="line">      &#125;,  </span><br><span class="line">      <span class="title function_">validator</span>(<span class="params">val</span>)&#123;  <span class="comment">// 自定义验证</span></span><br><span class="line">        <span class="keyword">return</span> val &gt; <span class="number">0</span></span><br><span class="line">      &#125;</span><br><span class="line">    &#125;</span><br><span class="line">  &#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure></li>
</ul>
<h3 id="双向绑定"><a href="#双向绑定" class="headerlink" title="双向绑定"></a>双向绑定</h3><blockquote>
<p>同步父子组件数据，注意不要在子组件中修改 props 接收的数据。</p>
</blockquote>
<ul>
<li>普通写法<ul>
<li>父组件监听自定义事件：<code>&lt;com @ut=&quot;val =&gt; pm = val&quot; :m=&quot;pm&quot;&gt;&lt;/com&gt;</code>。</li>
<li>子组件触发事件：<code>props: &#123; m: String &#125;、this.$emit(&#39;ut&#39;, newVal)</code>。</li>
</ul>
</li>
<li>使用 sync<ul>
<li>父组件：<code>&lt;child :s.sync=&quot;startDate&quot;&gt;&lt;/child&gt;</code>。</li>
<li>子组件：<code>props: &#123; s: String &#125;、this.$emit(&quot;update:s&quot;, val)</code>。</li>
</ul>
</li>
</ul>
<h3 id="祖孙组件"><a href="#祖孙组件" class="headerlink" title="祖孙组件"></a>祖孙组件</h3><blockquote>
<p><strong>$attrs</strong> 传递不被 prop 识别的属性 (class、style除外)、**$listeners**：传递组件的事件 (.native除外)。</p>
</blockquote>
  <figure class="highlight js"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">// com.vue</span></span><br><span class="line">&lt;child sex=<span class="string">&quot;男&quot;</span> width=<span class="string">&quot;80&quot;</span> height=<span class="string">&quot;80&quot;</span> @change=<span class="string">&quot;change&quot;</span>&gt;&lt;/child&gt;</span><br><span class="line"></span><br><span class="line"><span class="comment">// child.vue</span></span><br><span class="line"><span class="language-xml"><span class="tag">&lt;<span class="name">grand</span> <span class="attr">v-bind</span>=<span class="string">&quot;$attrs&quot;</span> <span class="attr">v-on</span>=<span class="string">&quot;$listeners&quot;</span>&gt;</span><span class="tag">&lt;/<span class="name">grand</span>&gt;</span></span></span><br><span class="line"></span><br><span class="line"><span class="comment">// grand.vue</span></span><br><span class="line"><span class="keyword">export</span> <span class="keyword">default</span> &#123;</span><br><span class="line">  <span class="attr">props</span>: [<span class="string">&#x27;sex&#x27;</span>],</span><br><span class="line">  <span class="attr">inheritAttrs</span>: <span class="literal">false</span>,  <span class="comment">// 去掉默认行为</span></span><br><span class="line">  <span class="title function_">mounted</span>(<span class="params"></span>) &#123;</span><br><span class="line">    <span class="comment">// &#123; width: &quot;80&quot;, height: &quot;80&quot; &#125;</span></span><br><span class="line">    <span class="variable language_">console</span>.<span class="title function_">log</span>(<span class="variable language_">this</span>.<span class="property">$attrs</span>)</span><br><span class="line"></span><br><span class="line">    <span class="comment">// change 事件</span></span><br><span class="line">    <span class="variable language_">console</span>.<span class="title function_">log</span>(<span class="variable language_">this</span>.<span class="property">$listeners</span>)</span><br><span class="line">  &#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>

<h3 id="provide、inject"><a href="#provide、inject" class="headerlink" title="provide、inject"></a>provide、inject</h3><blockquote>
<p>允许一个祖先组件向其所有子孙后代注入一个依赖，但是绑定并不是可响应的。</p>
</blockquote>
  <figure class="highlight js"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">// 父组件</span></span><br><span class="line"><span class="attr">provide</span>: &#123;      <span class="comment">// 一个对象</span></span><br><span class="line">  <span class="attr">foo</span>: <span class="string">&#x27;foo&#x27;</span>,</span><br><span class="line">  <span class="attr">fooMethod</span>: <span class="function">()=&gt;</span>&#123;</span><br><span class="line">    <span class="variable language_">console</span>.<span class="title function_">log</span>(<span class="string">&#x27;fooMethod 被调用&#x27;</span>)</span><br><span class="line">  &#125;</span><br><span class="line">&#125;,</span><br><span class="line"></span><br><span class="line"><span class="comment">// 子孙组件</span></span><br><span class="line"><span class="attr">inject</span>: [<span class="string">&#x27;foo&#x27;</span>,<span class="string">&#x27;fooMethod&#x27;</span>], <span class="comment">// 数组或对象，注入到子组件</span></span><br><span class="line"><span class="title function_">mounted</span>(<span class="params"></span>) &#123;</span><br><span class="line">  <span class="variable language_">this</span>.<span class="title function_">fooMethod</span>()</span><br><span class="line">  <span class="variable language_">console</span>.<span class="title function_">log</span>(<span class="variable language_">this</span>.<span class="property">foo</span>)</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>

<h2 id="template-标签"><a href="#template-标签" class="headerlink" title="template 标签"></a>template 标签</h2><blockquote>
<p>可看作一个不可见的包裹元素，主要用于分组的条件判断和列表渲染。</p>
</blockquote>
  <figure class="highlight js"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">// 条件渲染：通过 key 实现切换时清空内容。</span></span><br><span class="line">&lt;template v-<span class="keyword">if</span>=<span class="string">&quot;loginType === &#x27;username&#x27;&quot;</span>&gt;</span><br><span class="line">  <span class="language-xml"><span class="tag">&lt;<span class="name">label</span>&gt;</span>Username<span class="tag">&lt;/<span class="name">label</span>&gt;</span></span></span><br><span class="line">  <span class="language-xml"><span class="tag">&lt;<span class="name">input</span> <span class="attr">placeholder</span>=<span class="string">&quot;Enter your username&quot;</span>&gt;</span></span></span><br><span class="line"><span class="language-xml"><span class="tag">&lt;/<span class="name">template</span>&gt;</span></span></span><br><span class="line"><span class="language-xml"><span class="tag">&lt;<span class="name">template</span> <span class="attr">v-else</span>&gt;</span></span></span><br><span class="line"><span class="language-xml">  <span class="tag">&lt;<span class="name">label</span>&gt;</span>Email<span class="tag">&lt;/<span class="name">label</span>&gt;</span></span></span><br><span class="line"><span class="language-xml">  <span class="tag">&lt;<span class="name">input</span> <span class="attr">placeholder</span>=<span class="string">&quot;Enter your email address&quot;</span>&gt;</span></span></span><br><span class="line"><span class="language-xml"><span class="tag">&lt;/<span class="name">template</span>&gt;</span></span></span><br><span class="line"><span class="language-xml"></span></span><br><span class="line"><span class="language-xml">// 列表渲染</span></span><br><span class="line"><span class="language-xml"><span class="tag">&lt;<span class="name">ul</span>&gt;</span></span></span><br><span class="line"><span class="language-xml">  <span class="tag">&lt;<span class="name">template</span> <span class="attr">v-for</span>=<span class="string">&quot;item in items&quot;</span>&gt;</span></span></span><br><span class="line"><span class="language-xml">    <span class="tag">&lt;<span class="name">li</span>&gt;</span>&#123;&#123; item.msg &#125;&#125;<span class="tag">&lt;/<span class="name">li</span>&gt;</span></span></span><br><span class="line"><span class="language-xml">    <span class="tag">&lt;<span class="name">li</span> <span class="attr">class</span>=<span class="string">&quot;divider&quot;</span>&gt;</span><span class="tag">&lt;/<span class="name">li</span>&gt;</span></span></span><br><span class="line"><span class="language-xml">  <span class="tag">&lt;/<span class="name">template</span>&gt;</span></span></span><br><span class="line"><span class="language-xml"><span class="tag">&lt;/<span class="name">ul</span>&gt;</span></span></span><br></pre></td></tr></table></figure>


<h2 id="内置组件"><a href="#内置组件" class="headerlink" title="内置组件"></a>内置组件</h2><ul>
<li><strong>transition</strong>：单个元素&#x2F;组件的过渡效果</li>
<li><strong>transition-group</strong>：多个元素&#x2F;组件的过渡效果</li>
<li><strong>component</strong>：支持两个属性 is、inline-template</li>
<li><strong>keep-alive</strong>：保留组件状态或避免重新渲染</li>
<li><strong>slot</strong>：替换 slot 元素实现内容嵌套</li>
</ul>
<h2 id="特殊特性"><a href="#特殊特性" class="headerlink" title="特殊特性"></a>特殊特性</h2><ul>
<li><strong>key</strong>  <ul>
<li>管理可复用的元素：<code>&lt;router-view :key=&quot;$route.fullPath&quot;&gt;</code></li>
<li>减少运算来提高循环性能：<code>v-for=&quot;item in items&quot; :key=&quot;item.id&quot;</code></li>
</ul>
</li>
<li><strong>is</strong><ul>
<li>使用 v-bind:is 实现动态组件的切换效果<figure class="highlight xml"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">&lt;!-- change: this.index = (++this.ndex)%3 --&gt;</span></span><br><span class="line"><span class="tag">&lt;<span class="name">button</span> @<span class="attr">change</span>=<span class="string">&quot;change&quot;</span>&gt;</span><span class="tag">&lt;/<span class="name">button</span>&gt;</span></span><br><span class="line"><span class="tag">&lt;<span class="name">transition</span> <span class="attr">name</span>=<span class="string">&quot;fade&quot;</span> <span class="attr">appear</span>&gt;</span></span><br><span class="line">    <span class="tag">&lt;<span class="name">keep-alive</span>&gt;</span></span><br><span class="line">        <span class="tag">&lt;<span class="name">component</span> <span class="attr">:is</span>=<span class="string">&quot;views[index]&quot;</span>&gt;</span><span class="tag">&lt;/<span class="name">component</span>&gt;</span></span><br><span class="line">    <span class="tag">&lt;/<span class="name">keep-alive</span>&gt;</span></span><br><span class="line"><span class="tag">&lt;/<span class="name">transition</span>&gt;</span></span><br><span class="line"><span class="tag">&lt;<span class="name">transition</span> <span class="attr">name</span>=<span class="string">&quot;move&quot;</span> <span class="attr">mode</span>=<span class="string">&quot;out-in&quot;</span>&gt;</span></span><br><span class="line">    <span class="comment">&lt;!-- include：字符串/正则，只有匹配的组件被缓存 --&gt;</span></span><br><span class="line">    <span class="comment">&lt;!-- exclude：字符串/正则，任何匹配的组件都不会被缓存 --&gt;</span></span><br><span class="line">    <span class="tag">&lt;<span class="name">keep-alive</span> <span class="attr">:include</span>=<span class="string">&quot;tagList&quot;</span>&gt;</span></span><br><span class="line">        <span class="tag">&lt;<span class="name">router-view</span>&gt;</span><span class="tag">&lt;/<span class="name">router-view</span>&gt;</span></span><br><span class="line">    <span class="tag">&lt;/<span class="name">keep-alive</span>&gt;</span></span><br><span class="line"><span class="tag">&lt;/<span class="name">transition</span>&gt;</span></span><br></pre></td></tr></table></figure></li>
<li>用于在 ul 等受限制的 html 元素中绑定组件：<code>&lt;li is=&quot;com1&quot;&gt;&lt;/li&gt;</code></li>
</ul>
</li>
<li><strong>slot</strong> <ul>
<li>配合 slot 内置组件实现嵌套内容的相应显示。</li>
<li>没有 slot 时不显示嵌套内容，多个 slot 时需使用具名插槽 (添加 name 属性)。<figure class="highlight xml"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br></pre></td><td class="code"><pre><span class="line"><span class="tag">&lt;<span class="name">li</span> <span class="attr">is</span>=<span class="string">&quot;lis_slot&quot;</span>&gt;</span></span><br><span class="line">    <span class="tag">&lt;<span class="name">span</span> <span class="attr">slot</span>=<span class="string">&quot;first&quot;</span> @<span class="attr">click</span>=<span class="string">&quot;print&quot;</span>&gt;</span>first<span class="tag">&lt;/<span class="name">span</span>&gt;</span></span><br><span class="line">    <span class="tag">&lt;<span class="name">span</span> <span class="attr">slot</span>=<span class="string">&quot;second&quot;</span>&gt;</span>second<span class="tag">&lt;/<span class="name">span</span>&gt;</span></span><br><span class="line"><span class="tag">&lt;/<span class="name">li</span>&gt;</span></span><br><span class="line"><span class="comment">&lt;!-- lis_slot.vue --&gt;</span></span><br><span class="line"><span class="tag">&lt;<span class="name">template</span>&gt;</span></span><br><span class="line">    <span class="tag">&lt;<span class="name">li</span>&gt;</span></span><br><span class="line">       <span class="tag">&lt;<span class="name">slot</span> <span class="attr">name</span>=<span class="string">&quot;first&quot;</span>&gt;</span><span class="tag">&lt;/<span class="name">slot</span>&gt;</span> </span><br><span class="line">       <span class="tag">&lt;<span class="name">slot</span> <span class="attr">name</span>=<span class="string">&quot;second&quot;</span>&gt;</span><span class="tag">&lt;/<span class="name">slot</span>&gt;</span> </span><br><span class="line">    <span class="tag">&lt;/<span class="name">li</span>&gt;</span></span><br><span class="line"><span class="tag">&lt;/<span class="name">template</span>&gt;</span></span><br></pre></td></tr></table></figure></li>
</ul>
</li>
<li><strong>ref</strong>  <ul>
<li>获取当前 DOM 元素：<code>&lt;li ref=&quot;cur&quot;、this.$refs.cur&gt;&lt;/li&gt;</code></li>
<li>获取子组件实例对象：<code>&lt;my-com ref=&quot;com&quot;&gt;&lt;/my-com&gt;、this.$refs.com</code></li>
</ul>
</li>
</ul>
<h1 id="七、插件开发"><a href="#七、插件开发" class="headerlink" title="七、插件开发"></a>七、插件开发</h1><blockquote>
<p>本质是一个必须提供一个公开接口的对象或函数，用来扩展 vue 功能而实现组件无法实现的很多需求。插件可以封装组件，组件可以暴露数据给插件。</p>
</blockquote>
<h2 id="常规写法"><a href="#常规写法" class="headerlink" title="常规写法"></a>常规写法</h2>  <figure class="highlight js"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">// toast.js</span></span><br><span class="line"><span class="keyword">var</span> <span class="title class_">Toast</span> = &#123;&#125;;        </span><br><span class="line"><span class="title class_">Toast</span>.<span class="property">install</span> = <span class="keyword">function</span> (<span class="params">Vue, options</span>) &#123; </span><br><span class="line">  <span class="title class_">Vue</span>.<span class="property"><span class="keyword">prototype</span></span>.<span class="property">$msg</span> = <span class="string">&#x27;Hello World&#x27;</span>;</span><br><span class="line">&#125;</span><br><span class="line"><span class="variable language_">module</span>.<span class="property">exports</span> = <span class="title class_">Toast</span>;      </span><br><span class="line"></span><br><span class="line"><span class="comment">// main.js：Vue.use() 会自动调用 install() 并阻止相同插件注册多次</span></span><br><span class="line"><span class="keyword">import</span> <span class="title class_">Toast</span> <span class="keyword">from</span> <span class="string">&#x27;./toast.js&#x27;</span>;</span><br><span class="line"><span class="title class_">Vue</span>.<span class="title function_">use</span>(<span class="title class_">Toast</span>);  </span><br><span class="line"><span class="variable language_">console</span>.<span class="title function_">log</span>(<span class="variable language_">this</span>.<span class="property">$msg</span>);   <span class="comment">// Hello World</span></span><br></pre></td></tr></table></figure>


<h2 id="模板写法"><a href="#模板写法" class="headerlink" title="模板写法"></a>模板写法</h2>  <figure class="highlight js"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">export</span> <span class="keyword">default</span> &#123;</span><br><span class="line">  <span class="attr">install</span>: <span class="keyword">function</span> (<span class="params">Vue, options</span>) &#123; <span class="comment">//options一般是对象</span></span><br><span class="line">    <span class="comment">// 添加全局方法和属性</span></span><br><span class="line">    <span class="title class_">Vue</span>.<span class="property">myProperty</span> = <span class="string">&#x27;Hello Vue&#x27;</span>,    </span><br><span class="line">    <span class="title class_">Vue</span>.<span class="property">myGlobalMethod</span> = <span class="keyword">function</span> (<span class="params"></span>) &#123; &#125;, </span><br><span class="line">            </span><br><span class="line">    <span class="comment">// 添加全局资源：指令、过滤器、过渡等</span></span><br><span class="line">    <span class="title class_">Vue</span>.<span class="title function_">directive</span>(<span class="string">&#x27;focus&#x27;</span>, <span class="keyword">function</span>(<span class="params">el, binding, vnode, oldVnode</span>)&#123; &#125;)  </span><br><span class="line">    <span class="title class_">Vue</span>.<span class="title function_">filter</span>(<span class="string">&#x27;formatTime&#x27;</span>, <span class="keyword">function</span> (<span class="params">value</span>)&#123; &#125;)</span><br><span class="line"></span><br><span class="line">    <span class="comment">// 添加组件选项：混入 Vue 实例本身没有的方法</span></span><br><span class="line">    <span class="title class_">Vue</span>.<span class="title function_">mixin</span>(&#123;        </span><br><span class="line">      <span class="title function_">created</span>(<span class="params"></span>)&#123; &#125;,</span><br><span class="line">      <span class="attr">methods</span>: &#123; &#125;</span><br><span class="line">    &#125;) </span><br><span class="line"></span><br><span class="line">    <span class="comment">// 添加实例方法：调用时使用 this.$get()</span></span><br><span class="line">    <span class="title class_">Vue</span>.<span class="property"><span class="keyword">prototype</span></span>.<span class="property">$get</span> = <span class="keyword">function</span>(<span class="params"></span>)&#123; &#125;</span><br><span class="line">  &#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>



    </div>

    
    
    <div>
      
        <div>
    
        <div style="text-align:center;color: #ccc;font-size:14px;margin-top:20px;">-------------本文结束<i class="fa fa-paw"></i>感谢您的阅读-------------</div>
    
</div>

      
    </div>
    
        

<div>
<ul class="post-copyright">
  <li class="post-copyright-author">
    <strong>本文作者： </strong>chuangges
  </li>
  <li class="post-copyright-link">
    <strong>本文链接：</strong>
    <a href="https://chuangges.gitee.io/2019/06/05/5-1-vue%E9%A1%B9%E7%9B%AE%E6%9E%84%E5%BB%BA/" title="Vue 项目构建">https://chuangges.gitee.io/2019/06/05/5-1-vue项目构建/</a>
  </li>
  <li class="post-copyright-license">
    <strong>版权声明： </strong>本博客所有文章除特别声明外，均采用 <a href="https://creativecommons.org/licenses/by-nc-sa/4.0/zh_CN" rel="external nofollow noopener noreferrer" target="_blank"><i class="fab fa-fw fa-creative-commons"></i>BY-NC-SA</a> 许可协议。转载请注明出处！
  </li>
</ul>
</div>


      <footer class="post-footer">

        


        
    <div class="post-nav">
      <div class="post-nav-item">
    <a href="/2019/06/01/4-6-js%E7%BC%96%E7%A8%8B/" rel="prev" title="JS 编程范式">
      <i class="fa fa-chevron-left"></i> JS 编程范式
    </a></div>
      <div class="post-nav-item">
    <a href="/2019/06/10/5-2-vue%E5%B8%B8%E8%A7%81%E5%9C%BA%E6%99%AF/" rel="next" title="Vue 常见场景的解决方案">
      Vue 常见场景的解决方案 <i class="fa fa-chevron-right"></i>
    </a></div>
    </div>
      </footer>
    
  </article>
  
  
  



          </div>
          

<script>
  window.addEventListener('tabs:register', () => {
    let { activeClass } = CONFIG.comments;
    if (CONFIG.comments.storage) {
      activeClass = localStorage.getItem('comments_active') || activeClass;
    }
    if (activeClass) {
      let activeTab = document.querySelector(`a[href="#comment-${activeClass}"]`);
      if (activeTab) {
        activeTab.click();
      }
    }
  });
  if (CONFIG.comments.storage) {
    window.addEventListener('tabs:click', event => {
      if (!event.target.matches('.tabs-comment .tab-content .tab-pane')) return;
      let commentClass = event.target.classList[1];
      localStorage.setItem('comments_active', commentClass);
    });
  }
</script>

        </div>
          
  
  <div class="toggle sidebar-toggle">
    <span class="toggle-line toggle-line-first"></span>
    <span class="toggle-line toggle-line-middle"></span>
    <span class="toggle-line toggle-line-last"></span>
  </div>

  <aside class="sidebar">
    <div class="sidebar-inner">

      <ul class="sidebar-nav motion-element">
        <li class="sidebar-nav-toc">
          文章目录
        </li>
        <li class="sidebar-nav-overview">
          站点概览
        </li>
      </ul>

      <!--noindex-->
      <div class="post-toc-wrap sidebar-panel">
          <div class="post-toc motion-element"><ol class="nav"><li class="nav-item nav-level-1"><a class="nav-link" href="#%E4%B8%80%E3%80%81Vue-%E6%A1%86%E6%9E%B6"><span class="nav-number">1.</span> <span class="nav-text">一、Vue 框架</span></a><ol class="nav-child"><li class="nav-item nav-level-2"><a class="nav-link" href="#%E5%85%A8%E5%AE%B6%E6%A1%B6"><span class="nav-number">1.1.</span> <span class="nav-text">全家桶</span></a></li><li class="nav-item nav-level-2"><a class="nav-link" href="#%E5%8F%8C%E5%90%91%E7%BB%91%E5%AE%9A%E6%B5%81%E7%A8%8B"><span class="nav-number">1.2.</span> <span class="nav-text">双向绑定流程</span></a></li></ol></li><li class="nav-item nav-level-1"><a class="nav-link" href="#%E4%BA%8C%E3%80%81%E9%A1%B9%E7%9B%AE%E6%9E%84%E5%BB%BA"><span class="nav-number">2.</span> <span class="nav-text">二、项目构建</span></a><ol class="nav-child"><li class="nav-item nav-level-2"><a class="nav-link" href="#%E6%B5%8F%E8%A7%88%E5%99%A8%E6%B8%B2%E6%9F%93-SPA"><span class="nav-number">2.1.</span> <span class="nav-text">浏览器渲染 SPA</span></a></li><li class="nav-item nav-level-2"><a class="nav-link" href="#%E6%9C%8D%E5%8A%A1%E5%99%A8%E7%AB%AF%E6%B8%B2%E6%9F%93-SSR"><span class="nav-number">2.2.</span> <span class="nav-text">服务器端渲染 SSR</span></a></li><li class="nav-item nav-level-2"><a class="nav-link" href="#%E5%B8%B8%E7%94%A8%E9%85%8D%E7%BD%AE"><span class="nav-number">2.3.</span> <span class="nav-text">常用配置</span></a></li><li class="nav-item nav-level-2"><a class="nav-link" href="#%E6%80%A7%E8%83%BD%E4%BC%98%E5%8C%96"><span class="nav-number">2.4.</span> <span class="nav-text">性能优化</span></a></li></ol></li><li class="nav-item nav-level-1"><a class="nav-link" href="#%E4%B8%89%E3%80%81%E8%B7%AF%E7%94%B1%E6%8E%A7%E5%88%B6-Router"><span class="nav-number">3.</span> <span class="nav-text">三、路由控制 Router</span></a><ol class="nav-child"><li class="nav-item nav-level-2"><a class="nav-link" href="#%E5%9F%BA%E7%A1%80%E4%BD%BF%E7%94%A8"><span class="nav-number">3.1.</span> <span class="nav-text">基础使用</span></a></li><li class="nav-item nav-level-2"><a class="nav-link" href="#%E8%B7%AF%E7%94%B1%E9%85%8D%E7%BD%AE"><span class="nav-number">3.2.</span> <span class="nav-text">路由配置</span></a></li><li class="nav-item nav-level-2"><a class="nav-link" href="#%E8%B7%AF%E7%94%B1%E6%A8%A1%E5%BC%8F"><span class="nav-number">3.3.</span> <span class="nav-text">路由模式</span></a><ol class="nav-child"><li class="nav-item nav-level-3"><a class="nav-link" href="#%E4%B8%A4%E7%A7%8D%E6%A8%A1%E5%BC%8F"><span class="nav-number">3.3.1.</span> <span class="nav-text">两种模式</span></a></li><li class="nav-item nav-level-3"><a class="nav-link" href="#404-%E9%94%99%E8%AF%AF"><span class="nav-number">3.3.2.</span> <span class="nav-text">404 错误</span></a></li><li class="nav-item nav-level-3"><a class="nav-link" href="#%E6%B3%A8%E6%84%8F%E9%97%AE%E9%A2%98"><span class="nav-number">3.3.3.</span> <span class="nav-text">注意问题</span></a></li></ol></li><li class="nav-item nav-level-2"><a class="nav-link" href="#%E8%B7%AF%E7%94%B1%E8%B7%B3%E8%BD%AC"><span class="nav-number">3.4.</span> <span class="nav-text">路由跳转</span></a><ol class="nav-child"><li class="nav-item nav-level-3"><a class="nav-link" href="#%E7%BB%84%E4%BB%B6%E6%A0%87%E7%AD%BE"><span class="nav-number">3.4.1.</span> <span class="nav-text">组件标签</span></a></li><li class="nav-item nav-level-3"><a class="nav-link" href="#JS-%E7%BC%96%E7%A8%8B%E5%BC%8F%E5%AF%BC%E8%88%AA"><span class="nav-number">3.4.2.</span> <span class="nav-text">JS 编程式导航</span></a></li></ol></li><li class="nav-item nav-level-2"><a class="nav-link" href="#%E5%8A%A8%E6%80%81%E8%B7%AF%E7%94%B1%E4%BC%A0%E5%8F%82"><span class="nav-number">3.5.</span> <span class="nav-text">动态路由传参</span></a></li><li class="nav-item nav-level-2"><a class="nav-link" href="#%E5%AF%BC%E8%88%AA%E9%92%A9%E5%AD%90"><span class="nav-number">3.6.</span> <span class="nav-text">导航钩子</span></a><ol class="nav-child"><li class="nav-item nav-level-3"><a class="nav-link" href="#%E5%88%86%E7%B1%BB"><span class="nav-number">3.6.1.</span> <span class="nav-text">分类</span></a></li><li class="nav-item nav-level-3"><a class="nav-link" href="#%E5%8F%82%E6%95%B0"><span class="nav-number">3.6.2.</span> <span class="nav-text">参数</span></a></li></ol></li></ol></li><li class="nav-item nav-level-1"><a class="nav-link" href="#%E5%9B%9B%E3%80%81%E5%BC%82%E6%AD%A5%E9%80%9A%E4%BF%A1-Axios"><span class="nav-number">4.</span> <span class="nav-text">四、异步通信 Axios</span></a><ol class="nav-child"><li class="nav-item nav-level-2"><a class="nav-link" href="#%E5%9F%BA%E7%A1%80%E4%BD%BF%E7%94%A8-1"><span class="nav-number">4.1.</span> <span class="nav-text">基础使用</span></a></li><li class="nav-item nav-level-2"><a class="nav-link" href="#%E8%AF%B7%E6%B1%82-API"><span class="nav-number">4.2.</span> <span class="nav-text">请求 API</span></a></li><li class="nav-item nav-level-2"><a class="nav-link" href="#%E8%87%AA%E5%AE%9A%E4%B9%89%E9%85%8D%E7%BD%AE"><span class="nav-number">4.3.</span> <span class="nav-text">自定义配置</span></a><ol class="nav-child"><li class="nav-item nav-level-3"><a class="nav-link" href="#%E5%B0%81%E8%A3%85-axios"><span class="nav-number">4.3.1.</span> <span class="nav-text">封装 axios</span></a></li><li class="nav-item nav-level-3"><a class="nav-link" href="#%E5%BC%95%E7%94%A8%E6%96%B9%E6%B3%95"><span class="nav-number">4.3.2.</span> <span class="nav-text">引用方法</span></a></li><li class="nav-item nav-level-3"><a class="nav-link" href="#%E5%8A%A0%E5%AF%86%E6%96%B9%E6%B3%95"><span class="nav-number">4.3.3.</span> <span class="nav-text">加密方法</span></a></li></ol></li></ol></li><li class="nav-item nav-level-1"><a class="nav-link" href="#%E4%BA%94%E3%80%81%E7%8A%B6%E6%80%81%E7%AE%A1%E7%90%86-Vuex"><span class="nav-number">5.</span> <span class="nav-text">五、状态管理 Vuex</span></a><ol class="nav-child"><li class="nav-item nav-level-2"><a class="nav-link" href="#%E6%A0%B8%E5%BF%83%E6%A6%82%E5%BF%B5"><span class="nav-number">5.1.</span> <span class="nav-text">核心概念</span></a></li><li class="nav-item nav-level-2"><a class="nav-link" href="#%E4%B8%BB%E8%A6%81%E7%89%B9%E7%82%B9"><span class="nav-number">5.2.</span> <span class="nav-text">主要特点</span></a></li><li class="nav-item nav-level-2"><a class="nav-link" href="#%E7%9B%AE%E5%BD%95%E7%BB%93%E6%9E%84"><span class="nav-number">5.3.</span> <span class="nav-text">目录结构</span></a></li><li class="nav-item nav-level-2"><a class="nav-link" href="#%E8%87%AA%E5%AE%9A%E4%B9%89%E9%85%8D%E7%BD%AE-1"><span class="nav-number">5.4.</span> <span class="nav-text">自定义配置</span></a><ol class="nav-child"><li class="nav-item nav-level-3"><a class="nav-link" href="#%E5%8D%95%E4%B8%AA%E6%96%87%E4%BB%B6"><span class="nav-number">5.4.1.</span> <span class="nav-text">单个文件</span></a></li></ol></li><li class="nav-item nav-level-2"><a class="nav-link" href="#%E5%85%A8%E5%B1%80%E5%BC%95%E7%94%A8"><span class="nav-number">5.5.</span> <span class="nav-text">全局引用</span></a></li><li class="nav-item nav-level-2"><a class="nav-link" href="#%E7%BB%84%E4%BB%B6%E4%BD%BF%E7%94%A8"><span class="nav-number">5.6.</span> <span class="nav-text">组件使用</span></a></li><li class="nav-item nav-level-2"><a class="nav-link" href="#%E7%AE%80%E5%8D%95%E7%94%A8%E6%B3%95"><span class="nav-number">5.7.</span> <span class="nav-text">简单用法</span></a></li></ol></li><li class="nav-item nav-level-1"><a class="nav-link" href="#%E5%85%AD%E3%80%81%E7%BB%84%E4%BB%B6%E5%8C%96%E5%BC%80%E5%8F%91"><span class="nav-number">6.</span> <span class="nav-text">六、组件化开发</span></a><ol class="nav-child"><li class="nav-item nav-level-2"><a class="nav-link" href="#%E7%BB%84%E4%BB%B6%E5%AE%9E%E4%BE%8B%E5%8C%96"><span class="nav-number">6.1.</span> <span class="nav-text">组件实例化</span></a></li><li class="nav-item nav-level-2"><a class="nav-link" href="#%E7%BB%84%E4%BB%B6%E5%AE%9A%E4%B9%89"><span class="nav-number">6.2.</span> <span class="nav-text">组件定义</span></a></li><li class="nav-item nav-level-2"><a class="nav-link" href="#%E7%94%9F%E5%91%BD%E5%91%A8%E6%9C%9F"><span class="nav-number">6.3.</span> <span class="nav-text">生命周期</span></a></li><li class="nav-item nav-level-2"><a class="nav-link" href="#%E5%86%85%E7%BD%AE%E6%8C%87%E4%BB%A4"><span class="nav-number">6.4.</span> <span class="nav-text">内置指令</span></a></li><li class="nav-item nav-level-2"><a class="nav-link" href="#%E7%BB%84%E4%BB%B6%E9%80%9A%E4%BF%A1"><span class="nav-number">6.5.</span> <span class="nav-text">组件通信</span></a><ol class="nav-child"><li class="nav-item nav-level-3"><a class="nav-link" href="#%E7%88%B6%E5%AD%90%E7%BB%84%E4%BB%B6"><span class="nav-number">6.5.1.</span> <span class="nav-text">父子组件</span></a></li><li class="nav-item nav-level-3"><a class="nav-link" href="#%E5%8F%8C%E5%90%91%E7%BB%91%E5%AE%9A"><span class="nav-number">6.5.2.</span> <span class="nav-text">双向绑定</span></a></li><li class="nav-item nav-level-3"><a class="nav-link" href="#%E7%A5%96%E5%AD%99%E7%BB%84%E4%BB%B6"><span class="nav-number">6.5.3.</span> <span class="nav-text">祖孙组件</span></a></li><li class="nav-item nav-level-3"><a class="nav-link" href="#provide%E3%80%81inject"><span class="nav-number">6.5.4.</span> <span class="nav-text">provide、inject</span></a></li></ol></li><li class="nav-item nav-level-2"><a class="nav-link" href="#template-%E6%A0%87%E7%AD%BE"><span class="nav-number">6.6.</span> <span class="nav-text">template 标签</span></a></li><li class="nav-item nav-level-2"><a class="nav-link" href="#%E5%86%85%E7%BD%AE%E7%BB%84%E4%BB%B6"><span class="nav-number">6.7.</span> <span class="nav-text">内置组件</span></a></li><li class="nav-item nav-level-2"><a class="nav-link" href="#%E7%89%B9%E6%AE%8A%E7%89%B9%E6%80%A7"><span class="nav-number">6.8.</span> <span class="nav-text">特殊特性</span></a></li></ol></li><li class="nav-item nav-level-1"><a class="nav-link" href="#%E4%B8%83%E3%80%81%E6%8F%92%E4%BB%B6%E5%BC%80%E5%8F%91"><span class="nav-number">7.</span> <span class="nav-text">七、插件开发</span></a><ol class="nav-child"><li class="nav-item nav-level-2"><a class="nav-link" href="#%E5%B8%B8%E8%A7%84%E5%86%99%E6%B3%95"><span class="nav-number">7.1.</span> <span class="nav-text">常规写法</span></a></li><li class="nav-item nav-level-2"><a class="nav-link" href="#%E6%A8%A1%E6%9D%BF%E5%86%99%E6%B3%95"><span class="nav-number">7.2.</span> <span class="nav-text">模板写法</span></a></li></ol></li></ol></div>
      </div>
      <!--/noindex-->

      <div class="site-overview-wrap sidebar-panel">
        <div class="site-author motion-element" itemprop="author" itemscope itemtype="http://schema.org/Person">
    <img class="site-author-image" itemprop="image" alt="chuangges" src="" data-original="/images/chuang.png">
  <p class="site-author-name" itemprop="name">chuangges</p>
  <div class="site-description" itemprop="description">chuangge's blog.</div>
</div>
<div class="site-state-wrap motion-element">
  <nav class="site-state">
      <div class="site-state-item site-state-posts">
          <a href="/archives/">
        
          <span class="site-state-item-count">39</span>
          <span class="site-state-item-name">日志</span>
        </a>
      </div>
      <div class="site-state-item site-state-categories">
            <a href="/categories/">
          
        <span class="site-state-item-count">7</span>
        <span class="site-state-item-name">分类</span></a>
      </div>
      <div class="site-state-item site-state-tags">
            <a href="/tags/">
          
        <span class="site-state-item-count">7</span>
        <span class="site-state-item-name">标签</span></a>
      </div>
  </nav>
</div>
  <div class="links-of-author motion-element">
      <span class="links-of-author-item">
        <a href="https://github.com/chuangges" title="GitHub → https:&#x2F;&#x2F;github.com&#x2F;chuangges" rel="external nofollow noopener noreferrer" target="_blank"><i class="fab fa-github fa-fw"></i>GitHub</a>
      </span>
      <span class="links-of-author-item">
        <a href="https://stackoverflow.com/yourname" title="StackOverflow → https:&#x2F;&#x2F;stackoverflow.com&#x2F;yourname" rel="external nofollow noopener noreferrer" target="_blank"><i class="fab fa-stack-overflow fa-fw"></i>StackOverflow</a>
      </span>
  </div>


  <div class="links-of-blogroll motion-element">
    <div class="links-of-blogroll-title"><i class="fa fa-link fa-fw"></i>
      友情链接
    </div>
    <ul class="links-of-blogroll-list">
        <li class="links-of-blogroll-item">
          <a href="https://juejin.im/" title="https:&#x2F;&#x2F;juejin.im&#x2F;" rel="external nofollow noopener noreferrer" target="_blank">掘金</a>
        </li>
        <li class="links-of-blogroll-item">
          <a href="https://www.nowcoder.com/" title="https:&#x2F;&#x2F;www.nowcoder.com&#x2F;" rel="external nofollow noopener noreferrer" target="_blank">牛客网</a>
        </li>
        <li class="links-of-blogroll-item">
          <a href="https://www.docschina.org/" title="https:&#x2F;&#x2F;www.docschina.org&#x2F;" rel="external nofollow noopener noreferrer" target="_blank">印记中文</a>
        </li>
        <li class="links-of-blogroll-item">
          <a href="http://tool.lu/" title="http:&#x2F;&#x2F;tool.lu&#x2F;" rel="external nofollow noopener noreferrer" target="_blank">在线工具</a>
        </li>
        <li class="links-of-blogroll-item">
          <a href="https://tinypng.com/" title="https:&#x2F;&#x2F;tinypng.com&#x2F;" rel="external nofollow noopener noreferrer" target="_blank">图片压缩</a>
        </li>
        <li class="links-of-blogroll-item">
          <a href="https://bigjpg.com/" title="https:&#x2F;&#x2F;bigjpg.com&#x2F;" rel="external nofollow noopener noreferrer" target="_blank">图片放大</a>
        </li>
        <li class="links-of-blogroll-item">
          <a href="https://tool.chinaz.com/" title="https:&#x2F;&#x2F;tool.chinaz.com&#x2F;" rel="external nofollow noopener noreferrer" target="_blank">站长工具</a>
        </li>
        <li class="links-of-blogroll-item">
          <a href="https://learn-anything.xyz/" title="https:&#x2F;&#x2F;learn-anything.xyz&#x2F;" rel="external nofollow noopener noreferrer" target="_blank">Learn-Anything</a>
        </li>
        <li class="links-of-blogroll-item">
          <a href="https://stackoverflow.com/" title="https:&#x2F;&#x2F;stackoverflow.com&#x2F;" rel="external nofollow noopener noreferrer" target="_blank">Stack-Overflow</a>
        </li>
    </ul>
  </div>

      </div>

    </div>
  </aside>
  <div id="sidebar-dimmer"></div>


      </div>
    </main>

    <footer class="footer">
      <div class="footer-inner">
        

        

<div class="copyright">
  
  &copy; 
  <span itemprop="copyrightYear">2024</span>
  <span class="with-love">
    <i class="fa fa-heart"></i>
  </span>
  <span class="author" itemprop="copyrightHolder">chuangge</span>
    <span class="post-meta-divider">|</span>
    <span class="post-meta-item-icon">
      <i class="fa fa-chart-area"></i>
    </span>
    <span title="站点总字数">1m</span>
    <span class="post-meta-divider">|</span>
    <span class="post-meta-item-icon">
      <i class="fa fa-coffee"></i>
    </span>
    <span title="站点阅读时长">15:14</span>
</div>
  <div class="powered-by">由 <a href="https://hexo.io/" class="theme-link" rel="external nofollow noopener noreferrer" target="_blank">Hexo</a> & <a href="https://pisces.theme-next.org/" class="theme-link" rel="external nofollow noopener noreferrer" target="_blank">NexT.Pisces</a> 强力驱动
  </div>

        








      </div>
    </footer>
  </div>

  
  <script src="/lib/anime.min.js"></script>
  <script src="/lib/velocity/velocity.min.js"></script>
  <script src="/lib/velocity/velocity.ui.min.js"></script>

<script src="/js/utils.js"></script>

<script src="/js/motion.js"></script>


<script src="/js/schemes/pisces.js"></script>


<script src="/js/next-boot.js"></script>




  















  

  

<script src="/live2dw/lib/L2Dwidget.min.js?094cbace49a39548bed64abff5988b05"></script><script>L2Dwidget.init({"pluginRootPath":"live2dw/","pluginJsPath":"lib/","pluginModelPath":"assets/","model":{"jsonPath":"/live2dw/assets/tororo.model.json"},"display":{"position":"left","width":180,"height":360},"mobile":{"show":false},"react":{"opacityDefault":1,"opacityOnHover":1},"log":false,"tagMode":false});</script>
        <style>
            [bg-lazy] {
                background-image: none !important;
                background-color: #eee !important;
            }
        </style>
        <script>
            window.imageLazyLoadSetting = {
                isSPA: false,
                preloadRatio: 1,
                processImages: null,
            };
        </script><script>window.addEventListener("load",function(){var t=/\.(gif|jpg|jpeg|tiff|png)$/i,r=/^data:image\/[a-z]+;base64,/;Array.prototype.slice.call(document.querySelectorAll("img[data-original]")).forEach(function(a){var e=a.parentNode;"A"===e.tagName&&(e.href.match(t)||e.href.match(r))&&(e.href=a.dataset.original)})});</script><script>!function(e){e.imageLazyLoadSetting.processImages=t;var n=e.imageLazyLoadSetting.isSPA,i=e.imageLazyLoadSetting.preloadRatio||1,r=o();function o(){var t=Array.prototype.slice.call(document.querySelectorAll("img[data-original]")),e=Array.prototype.slice.call(document.querySelectorAll("[bg-lazy]"));return t.concat(e)}function t(){n&&(r=o());for(var t,a=0;a<r.length;a++)0<=(t=(t=r[a]).getBoundingClientRect()).bottom&&0<=t.left&&t.top<=(e.innerHeight*i||document.documentElement.clientHeight*i)&&function(){var t,e,n,i,o=r[a];e=function(){r=r.filter(function(t){return o!==t})},(t=o).hasAttribute("bg-lazy")?(t.removeAttribute("bg-lazy"),e&&e()):(n=new Image,i=t.getAttribute("data-original"),n.onload=function(){t.src=i,t.removeAttribute("data-original"),e&&e()},t.src!==i&&(n.src=i))}()}function a(){clearTimeout(t.tId),t.tId=setTimeout(t,500)}t(),document.addEventListener("scroll",a),e.addEventListener("resize",a),e.addEventListener("orientationchange",a)}(this);</script></body>
</html>
